What is the nil or "empty" countable range in Swift? - swift3

In Swift3,
let highestIndex = 7
for index in 1 ..< highestIndex {
latter(index)
}
however,
let highestIndex = 0, or anything smaller
for index in 1 ..< highestIndex {
latter(index)
}
that crashes.
So, the ..< operator is impractical in most situations.
So, perhaps, something like this ...
for index in (1 ..< highestIndex).safely() {
latter(index)
}
How would one write the extension safely ?
Or at worst just a function safely(from,to) which returns a CountableRange, or, an "empty" (?) countable range? (I don't understand if a Swift extension can "catch" an error?)

Sticking as closely to the ..< operator as possible the following would be an appropriate implementation of safely.
public func safely<Bound>(_ minimum: Bound, _ maximum: Bound) -> CountableRange<Bound> where Bound : _Strideable & Comparable, Bound.Stride : Integer {
if maximum < minimum {
return CountableRange(uncheckedBounds: (lower: minimum, upper: minimum))
}
return CountableRange(uncheckedBounds: (lower: minimum, upper: maximum))
}
let one = safely(0, 12) // CountableRange(0..<12)
let two = safely(15, 12) // CountableRange(15..<15)
one.isEmpty // false
two.isEmpty // true
You might want to consider giving the parameters better names to indicate wether or not they are inclusive / exclusive bounds, etc.
Creating an extension and adding a .safely() will not work since the bounds are checked when creating the CountableRange before the call to safely could even be done.

I am a fan of simple solutions:
let lowerIndex = 1
let higherIndex = 0
for index in lowerIndex ..< max(lowerIndex, higherIndex) {
latter(index)
}

I'm able to get this to work fine:
for index in 1 ..< 1 {
latter(index)
}
For the <1 case, I recommend something like this:
guard highestIndex > 0 else { return }
for index in 1 ..< highestIndex {
latter(index)
}

Related

When to use `std::cmp::ordering` instead of an `if` statement in Rust

When should I use std::cmp::ordering in a match block instead of using an if/else if statement? Is readability the only difference?
For example:
use std::cmp::Ordering;
fn main() {
match 2.cmp(&2) {
Ordering::Less => println!("Less than 2."),
Ordering::Greater => println!("Greater than 2."),
Ordering::Equal => println!("Equal to 2."),
}
}
vs.
fn main() {
if 1 < 2 {
println!("less than 2.");
} else if 1 > 2 {
println!("Greater than 2.");
} else if 1 == 2 {
println!("Equal to 2.");
}
}
Is readability the only difference?
I would say it's more of a DRY (Don't Repeat Yourself) thing.
If you look at the second sample, it's messy:
fn main() {
if 1 < 2 {
println!("less than 2.");
} else if 1 > 2 {
println!("Greater than 2.");
} else if 1 == 2 {
println!("Equal to 2.");
}
}
There is no else clause. If you mess up the conditions it'll just do nothing.
If the last one was an else clause, you'd still better put an assert!(1 == 2) inside to make sure that it's only taken when the two are equal (and not because you made a mistake in the previous conditions).
And even then you would still have a repetition between 1 < 2 and 1 > 2.
Compare that to the match:
fn main() {
match 2.cmp(&2) {
Ordering::Less => println!("Less than 2."),
Ordering::Greater => println!("Greater than 2."),
Ordering::Equal => println!("Equal to 2."),
}
}
You cannot accidentally forget a case, it's guaranteed to be exhaustive.
The condition is only written once, no need to "reverse" it or anything.
Therefore, if vs match is a matter of number of different outputs really:
use if if there is one or two branches,
use match if there are three branches or more.
A match is just more maintainable than an if/else chain.
Note: I personally think that cmp is rarely used directly. It is more meant as an implementation device, allowing you to implement a single function to get all 4 inequality operators. Coming from C++, it's a relief...

Swift 3 and code converter for looping arrays reversely

I have this code which is not compatible with swift3
for var i = FCatalogIdx-1; i > -1; i -=1 {
// access items in array FCaalogArr
}
Code converter suggest converting to
for i in ((-1 + 1)...FCatalogIdx-1).reversed() {
which seems to be the the same as:
for i in (0...FCatalogIdx-1).reversed() {
Is this the closest I can get to my old code? And if so, is it recommended to use the code converter suggestion - the (-1 + 1) looks ugly, but I suspect it is to give a hint of the original c-style loop logic?
You shouldn't use the (-1+1) because that is just needlessly confusing. Also, use the half-open range operator ..< to create a range that doesn't include the final index:
for i in (0 ..< FCatalogIdx).reversed() {
}
The advantage of the half-open range operator ..< over the closed range operator ... is that it is possible to create an empty range.
Consider this example:
let n = 0
for i in 0 ..< n {
print("hello") // range is empty, so this is never printed
}
for i in 0 ... n-1 { // fatal error: Can't form Range with upperBound < lowerBound
print("hello")
}
for i in FCaalogArr.indicies.reversed() would be better assuming FCaalogIdx is the last index of the array

What's Swift's "fromAfter" call in array slices?

Swift 3 has upTo and through
which are noninclusive, inclusive respectively
func prefix(upTo: Int)
Returns a subsequence from the start of the collection up to, but not including, the specified position.
.
func prefix(through: Int)
Returns a subsequence from the start of the collection through the specified position.
for the other end it has from
func suffix(from: Int)
Returns a subsequence from the specified position to the end of the collection.
which seems to be inclusive
What's the non-inclusive call at the far end??
// sum the numbers before, and after, an index i...
let lo = A.prefix(upTo: i).reduce(0,+) // means noninclusive
let hi = A.suffix(from: i+1).reduce(0,+) // 'from' seems to mean inclusive
what's the call I don't know? It sucks to have to write from with +1.
There is currently no non-inclusive suffix method for for Collection types in the stdlib, but for this use case, you can readily implement your own by combining suffix(from:) with dropFirst(_:) (which, imho, better shows intent than from: idx+1), e.g.
extension Collection where SubSequence == SubSequence.SubSequence {
public func suffix(after start: Index) -> SubSequence {
return suffix(from: start).dropFirst(1)
}
}
Applied to your example (separately sum numbers before and after a given partitioning number (or, index of), not including the partitioning one):
/* in this example, invalid indices will yield a full-array sum into
lo or hi, depending on high or low index out of bounds, respectively */
func splitSum(of arr: [Int], at: Int) -> (Int, Int) {
guard at < arr.count else { return (arr.reduce(0, +), 0) }
guard at >= 0 else { return (0, arr.reduce(0, +)) }
let lo = arr.prefix(upTo: at).reduce(0, +)
let hi = arr.suffix(after: at).reduce(0, +)
return (lo, hi)
}
// example usage
let arr = [Int](repeating: 1, count: 10)
print(splitSum(of: arr, at: 4)) // (4, 5)
Leaving the subject of a non-inclusive suffix method, an alternative approach to your split sum calculation would be to use one of the split(...) methods for Collection types:
func splitSum(of arr: [Int], at: Int) -> (Int, Int) {
guard at < arr.count else { return (arr.reduce(0, +), 0) }
guard at >= 0 else { return (0, arr.reduce(0, +)) }
let sums = arr.enumerated()
.split (omittingEmptySubsequences: false) { $0.0 == at }
.map { $0.reduce(0) { $0 + $1.1 } }
guard let lo = sums.first, let hi = sums.last else { fatalError() }
return (lo, hi)
}
// example: same as above
I believe the split version is a bit more verbose, however, and also semantically poorer at showing the intent of the code.

Replacing or substituting a large number of if..else statements that have specific ranges

My input is a range of positive integer values between 0 to 200, and I have to classify each value between ranges:0-24, 25-49, 50-74, 75-99, 100-124, 125-149, 150-174 and 175-200 and then output how many values lie is what range. The values are stored in a text file(TextScores.txt) separated with commas. Here is the code.
ifstream file;
string x;
int y,j;
int count[8]={0};
j=0;
file.open("C:\\Users\\USER\\Desktop\\TestScores.txt");
while(getline(file,x,','))
{
y = stoi(x);
if(y<=24)
{
count[0]++;
}
else
if (y>=25 && y<=49)
{
count[1]++;
}
else
if (y>=50 && y<=74)
{
count[2]++;
}
else
if (y>=75 && y<=99)
{
count[3]++;
}
else
if (y>=100 && y<=124)
{
count[4]++;
}
else
if (y>=124 && y<=149)
{
count[5]++;
}
else
if (y>=150 && y<=174)
{
count[6]++;
}
else
if (y>=175 && y<=200)
{
count[7]++;
}
}
for (int i=0; i<=7; i++)
{
cout<<"Test scores between range "<<setw(3)<<j<<" to "
<<setw(3)<<j+25<<" are "<<count[i]<<endl;
j+=25;
}
Alternatives for the hefty amount of if..else statements can be:
y<=24 ? count[0]++ : y>=25 && y<=49 ? count[1]++ : y>=50 && y<=74
count[2]++ : y>=75 && y<=99 ? count[3]++ : y>=100 && y<=124 ? count[4]++ :
y>=125 && y<=149 ? count[5]++ : y>=150 && y<=174 ? count[6]++ : count[7]++;
Or switch statements. Anyone got any other suggestions?
Note: I studied a little bit of range based for loops but I don't know precisely how to go about them in this situation. If anybody knows how to apply them on the problem specified it will be appreciated. I don't want to go into O.O.P. Thanks.
Notice that your ranges are exactly 25 apart. If you perform integer division on y, you can use that to index into your count array. There is a special case for y=200 because that would return 8, which is outside of your array size.
if (y >=0 && y < 200)
++count[y/25];
else if (y == 200)
++count[7];
As Richard Hodges states in his comment, a shorter, more idiomatic way of writing this would be just:
++count[ std::min(7, y/25) ];
You will need to include the algorithm header to access this function.
Define a struct
struct limit {
int min;
int max;
};
Then an array of that
struct limit limits[] = { {0, 24} {25, 49}, {50, 74} /* and so on */ };
Then loop over the array
while(getline(file,x,','))
{
y = stoi(x);
for (int i = 0; i < sizeof(limits)/sizeof(limits[0]); i++) {
if (y >= limits[i].min && y <= limits[i].max) {
count[i]++;
}
}
}
Of course if the pairs are equidistant the array approach doesn't make sense. Go with my proposal if you need arbitrary integer ranges.
Also note that my proposal is plain C, opposed to the STL based answer from πάντα ῥεῖ.
Besides that you can use a simple mathematical solution for your task, because there are apparently fixed steps of 25 (as was mentioned in this answer), in order to create a generic solution, you could use a std::map<std::pair<int,int>,int> that holds all the possible ranges as key values and run a loop for counting:
std::map<std::pair<int,int>,int> rangeCounts =
{ { 0, 25 }, 0 ,
{ 24, 50 }, 0 ,
{ 49, 75 }, 0 ,
// ...
{ 174, 200 }, 0 ,
};
for(std::unordered_map<std::pair<int,int>,int>::iterator it = rangeCounts.begin();
it != rangeCounts.end();
++it) {
if(y > (it->first).first && y < (it->first).second)
++(it->second);
}
As a side note: Your current range delimiters look strange because of these overlapping lower and higher limits (if else cascade or not).
and I have to classify each value between ranges:0-24, 25-49, 50-74, 75-99, 100-124, 125-149, 150-174 and 175-200 and then output how many values lie is what range.
The ranges (with my example) should look like:
std::map<std::pair<int,int>,int> rangeCounts =
{ { 0, 24 }, 0 ,
{ 25, 49 }, 0 ,
{ 50, 74 }, 0 ,
// ...
{ 175, 200 }, 0 ,
};
and the range condition
if(y >= (it->first).first && y <= (it->first).second)
Note: I studied a little bit of range based for loops but I don't know precisely how to go about them in this situation.
These have nothing to do with your range check problem. A range based for() loop just allow to iterate over a containers contents based on the std::begin() and std::end() standard functions implicitely.
So a range based for loop implementation for my sample would look like
for(auto& entry : rangeCounts) {
if(y >= entry.first.first && y =< entry.first.second)
++entry.second;
}
You have a pattern in the if..else statements. You are making constant range size of 25. So, you should use the division by 25 to find the correct case to make the increment:
while(getline(file,x,','))
{
y = stoi(x);
count[y / 25]++;
}

Determining if a number is either a multiple of ten or within a particular set of ranges

I have a few loops that I need in my program. I can write out the pseudo code, but I'm not entirely sure how to write them logically.
I need -
if (num is a multiple of 10) { do this }
if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90
This is for a snakes and ladders board game, if it makes any more sense for my question.
I imagine the first if statement I'll need to use modulus. Would if (num == 100%10) be correct?
The second one I have no idea. I can write it out like if (num > 10 && num is < 21 || etc.), but there has to be something smarter than that.
For the first one, to check if a number is a multiple of use:
if (num % 10 == 0) // It's divisible by 10
For the second one:
if(((num - 1) / 10) % 2 == 1 && num <= 100)
But that's rather dense, and you might be better off just listing the options explicitly.
Now that you've given a better idea of what you are doing, I'd write the second one as:
int getRow(int num) {
return (num - 1) / 10;
}
if (getRow(num) % 2 == 0) {
}
It's the same logic, but by using the function we get a clearer idea of what it means.
if (num is a multiple of 10) { do this }
if (num % 10 == 0) {
// Do something
}
if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
The trick here is to look for some sort of commonality among the ranges. Of course, you can always use the "brute force" method:
if ((num > 10 && num <= 20) ||
(num > 30 && num <= 40) ||
(num > 50 && num <= 60) ||
(num > 70 && num <= 80) ||
(num > 90 && num <= 100)) {
// Do something
}
But you might notice that, if you subtract 1 from num, you'll have the ranges:
10-19, 30-39, 50-59, 70-79, 90-99
In other words, all two-digit numbers whose first digit is odd. Next, you need to come up with a formula that expresses this. You can get the first digit by dividing by 10, and you can test that it's odd by checking for a remainder of 1 when you divide by 2. Putting that all together:
if ((num > 0) && (num <= 100) && (((num - 1) / 10) % 2 == 1)) {
// Do something
}
Given the trade-off between longer but maintainable code and shorter "clever" code, I'd pick longer and clearer every time. At the very least, if you try to be clever, please, please include a comment that explains exactly what you're trying to accomplish.
It helps to assume the next developer to work on the code is armed and knows where you live. :-)
If you are using GCC or any compiler that supports case ranges you can do this, but your code will not be portable.
switch(num)
{
case 11 ... 20:
case 31 ... 40:
case 51 ... 60:
case 71 ... 80:
case 91 ... 100:
// Do something
break;
default:
// Do something else
break;
}
This is for future visitors more so than a beginner. For a more general, algorithm-like solution, you can take a list of starting and ending values and check if a passed value is within one of them:
template<typename It, typename Elem>
bool in_any_interval(It first, It last, const Elem &val) {
return std::any_of(first, last, [&val](const auto &p) {
return p.first <= val && val <= p.second;
});
}
For simplicity, I used a polymorphic lambda (C++14) instead of an explicit pair argument. This should also probably stick to using < and == to be consistent with the standard algorithms, but it works like this as long as Elem has <= defined for it. Anyway, it can be used like this:
std::pair<int, int> intervals[]{
{11, 20}, {31, 40}, {51, 60}, {71, 80}, {91, 100}
};
const int num = 15;
std::cout << in_any_interval(std::begin(intervals), std::end(intervals), num);
There's a live example here.
The first one is easy. You just need to apply the modulo operator to your num value:
if ( ( num % 10 ) == 0)
Since C++ is evaluating every number that is not 0 as true, you could also write:
if ( ! ( num % 10 ) ) // Does not have a residue when divided by 10
For the second one, I think this is cleaner to understand:
The pattern repeats every 20, so you can calculate modulo 20.
All elements you want will be in a row except the ones that are dividable by 20.
To get those too, just use num-1 or better num+19 to avoid dealing with negative numbers.
if ( ( ( num + 19 ) % 20 ) > 9 )
This is assuming the pattern repeats forever, so for 111-120 it would apply again, and so on. Otherwise you need to limit the numbers to 100:
if ( ( ( ( num + 19 ) % 20 ) > 9 ) && ( num <= 100 ) )
With a couple of good comments in the code, it can be written quite concisely and readably.
// Check if it's a multiple of 10
if (num % 10 == 0) { ... }
// Check for whether tens digit is zero or even (1-10, 21-30, ...)
if ((num / 10) % 2 == 0) { ... }
else { ... }
You basically explained the answer yourself, but here's the code just in case.
if((x % 10) == 0) {
// Do this
}
if((x > 10 && x < 21) || (x > 30 && x < 41) || (x > 50 && x < 61) || (x > 70 && x < 81) || (x > 90 && x < 101)) {
// Do this
}
You might be overthinking this.
if (x % 10)
{
.. code for 1..9 ..
} else
{
.. code for 0, 10, 20 etc.
}
The first line if (x % 10) works because (a) a value that is a multiple of 10 calculates as '0', other numbers result in their remainer, (b) a value of 0 in an if is considered false, any other value is true.
Edit:
To toggle back-and-forth in twenties, use the same trick. This time, the pivotal number is 10:
if (((x-1)/10) & 1)
{
.. code for 10, 30, ..
} else
{
.. code for 20, 40, etc.
}
x/10 returns any number from 0 to 9 as 0, 10 to 19 as 1 and so on. Testing on even or odd -- the & 1 -- tells you if it's even or odd. Since your ranges are actually "11 to 20", subtract 1 before testing.
A plea for readability
While you already have some good answers, I would like to recommend a programming technique that will make your code more readable for some future reader - that can be you in six months, a colleague asked to perform a code review, your successor, ...
This is to wrap any "clever" statements into a function that shows exactly (with its name) what it is doing. While there is a miniscule impact on performance (from "function calling overhead") this is truly negligible in a game situation like this.
Along the way you can sanitize your inputs - for example, test for "illegal" values. Thus you might end up with code like this - see how much more readable it is? The "helper functions" can be hidden away somewhere (the don't need to be in the main module: it is clear from their name what they do):
#include <stdio.h>
enum {NO, YES, WINNER};
enum {OUT_OF_RANGE=-1, ODD, EVEN};
int notInRange(int square) {
return(square < 1 || square > 100)?YES:NO;
}
int isEndOfRow(int square) {
if (notInRange(square)) return OUT_OF_RANGE;
if (square == 100) return WINNER; // I am making this up...
return (square % 10 == 0)? YES:NO;
}
int rowType(unsigned int square) {
// return 1 if square is in odd row (going to the right)
// and 0 if square is in even row (going to the left)
if (notInRange(square)) return OUT_OF_RANGE; // trap this error
int rowNum = (square - 1) / 10;
return (rowNum % 2 == 0) ? ODD:EVEN; // return 0 (ODD) for 1-10, 21-30 etc.
// and 1 (EVEN) for 11-20, 31-40, ...
}
int main(void) {
int a = 12;
int rt;
rt = rowType(a); // this replaces your obscure if statement
// and here is how you handle the possible return values:
switch(rt) {
case ODD:
printf("It is an odd row\n");
break;
case EVEN:
printf("It is an even row\n");
break;
case OUT_OF_RANGE:
printf("It is out of range\n");
break;
default:
printf("Unexpected return value from rowType!\n");
}
if(isEndOfRow(10)==YES) printf("10 is at the end of a row\n");
if(isEndOfRow(100)==WINNER) printf("We have a winner!\n");
}
For the first one:
if (x % 10 == 0)
will apply to:
10, 20, 30, .. 100 .. 1000 ...
For the second one:
if (((x-1) / 10) % 2 == 1)
will apply for:
11-20, 31-40, 51-60, ..
We basically first do x-1 to get:
10-19, 30-39, 50-59, ..
Then we divide them by 10 to get:
1, 3, 5, ..
So we check if this result is odd.
As others have pointed out, making the conditions more concise won't speed up the compilation or the execution, and it doesn't necessarily help with readability either.
It can help in making your program more flexible, in case you decide later that you want a toddler's version of the game on a 6 x 6 board, or an advanced version (that you can play all night long) on a 40 x 50 board.
So I would code it as follows:
// What is the size of the game board?
#define ROWS 10
#define COLUMNS 10
// The numbers of the squares go from 1 (bottom-left) to (ROWS * COLUMNS)
// (top-left if ROWS is even, or top-right if ROWS is odd)
#define firstSquare 1
#define lastSquare (ROWS * COLUMNS)
// We haven't started until we roll the die and move onto the first square,
// so there is an imaginary 'square zero'
#define notStarted(num) (num == 0)
// and we only win when we land exactly on the last square
#define finished(num) (num == lastSquare)
#define overShot(num) (num > lastSquare)
// We will number our rows from 1 to ROWS, and our columns from 1 to COLUMNS
// (apologies to C fanatics who believe the world should be zero-based, which would
// have simplified these expressions)
#define getRow(num) (((num - 1) / COLUMNS) + 1)
#define getCol(num) (((num - 1) % COLUMNS) + 1)
// What direction are we moving in?
// On rows 1, 3, 5, etc. we go from left to right
#define isLeftToRightRow(num) ((getRow(num) % 2) == 1)
// On rows 2, 4, 6, etc. we go from right to left
#define isRightToLeftRow(num) ((getRow(num) % 2) == 0)
// Are we on the last square in the row?
#define isLastInRow(num) (getCol(num) == COLUMNS)
// And finally we can get onto the code
if (notStarted(mySquare))
{
// Some code for when we haven't got our piece on the board yet
}
else
{
if (isLastInRow(mySquare))
{
// Some code for when we're on the last square in a row
}
if (isRightToLeftRow(mySquare))
{
// Some code for when we're travelling from right to left
}
else
{
// Some code for when we're travelling from left to right
}
}
Yes, it's verbose, but it makes it clear exactly what's happening on the game board.
If I was developing this game to display on a phone or tablet, I'd make ROWS and COLUMNS variables instead of constants, so they can be set dynamically (at the start of a game) to match the screen size and orientation.
I'd also allow the screen orientation to be changed at any time, mid-game - all you need to do is switch the values of ROWS and COLUMNS, while leaving everything else (the current square number that each player is on, and the start/end squares of all the snakes and ladders) unchanged.
Then you 'just' have to draw the board nicely, and write code for your animations (I assume that was the purpose of your if statements) ...
You can try the following:
// Multiple of 10
if ((num % 10) == 0)
{
// Do something
}
else if (((num / 10) % 2) != 0)
{
// 11-20, 31-40, 51-60, 71-80, 91-100
}
else
{
// Other case
}
I know that this question has so many answers, but I will thrown mine here anyway...
Taken from Steve McConnell's Code Complete, 2nd Edition:
"Stair-Step Access Tables:
Yet another kind of table access is the stair-step method. This access method isn’t as direct as an index structure, but it doesn’t waste as much data space. The general idea of stair-step structures, illustrated in Figure 18-5, is that entries in a table are valid for ranges of data rather than for distinct data points.
Figure 18-5 The stair-step approach categorizes each entry by determining the level at which it hits a “staircase.” The “step” it hits determines its category.
For example, if you’re writing a grading program, the “B” entry range might be from 75 percent to 90 percent. Here’s a range of grades you might have to program someday:
To use the stair-step method, you put the upper end of each range into a table and then write a loop to check a score against the upper end of each range. When you find the point at which the score first exceeds the top of a range, you know what the grade is. With the stair-step technique, you have to be careful to handle the endpoints of the ranges properly. Here’s the code in Visual Basic that assigns grades to a group of students based on this example:
Although this is a simple example, you can easily generalize it to handle multiple students, multiple grading schemes (for example, different grades for different point levels on different assignments), and changes in the grading scheme."
Code Complete, 2nd Edition, pages 426 - 428 (Chapter 18).