Absolutely-DRY conditionals in a language that doesn't allow goto? - goto

How do you fake conditionals that don't nest in a language that doesn't allow goto? I want to do the following:
if (condition1)
action1;
if (!condition1 && condition2)
action2;
if (!condition2 && condition3)
action3;
Without:
Needlessly evaluating any condition more than once.
Needlessly storing the result of any such evaluation in a variable.
Needlessly specifying more than once that any action should be performed.
The original snippet fails to meet requirement 1.
The following snippet fails to meet requirement 2:
if (condition1) {
action1;
c2 = false;
}
else if (c2 = condition2)
action2;
if (!c2 && condition3)
action3;
And the following snippet fails to meet requirement 3:
if (condition1) {
action1;
if (condition3)
action3;
}
else if (condition2)
action2;
else if (condition3)
action3;
EDIT:
It is impossible that condition1 and condition2 be true simultaneously.
It is impossible that condition2 and condition3 be true simultaneously.
Here is the original code (in JavaScript):
// If only the array of elements was specified,
// wrap it inside an object.
if (info.constructor !== Object)
info = {children: info};
// If no array of elements was specified, create
// an empty array of elements.
if (!info.children)
info.children = [];
// If, instead of an array of elements, we have
// a single element, wrap it inside an array.
if (info.children.constructor !== Array)
info.children = [info.children];

Truth Table
C1 C2 C3 Action
0 0 0 None
0 0 1 A3
0 1 0 A2
0 1 1 A2
1 0 0 A1
1 0 1 A1+A3
1 1 0 A1
1 1 1 A1
Is switch/case against the rules? :)
switch(C1*4 + C2*2 + C1) {
case 7: case 6: case 4: A1; break;
case 5: A1; A3; break;
case 3: case 2: A2; break;
case 1: A3; break;
}

So how do you do this with goto anyway? This immediately comes to mind, but doesn't have quite the same result:
if(condition1) {
action1;
goto a;
}
if(condition2) {
action2;
goto b;
}
a:
if(condition3) {
//This will run if condition1 && condition2 && condition3
action3;
}
b:
Either way, you do have a few tricks that can break out of nested "if"s. Try:
do {
if(condition1) {
action1;
} elseif(condition2) {
action2;
break;
}
if(condition3) {
action3;
}
} while(false);
It's essentially a goto, but...
That version will duplicate the goto construct that I imagined, rather than the one in the OP. Note that "return" works about the same, in case that looks cleaner in your code (and it might be able to push the hack a bit further by returning a boolean).

Related

Simplifying decision tree when working with map which has two keys and value as a slice

Can this logic not be simplified more, the code works, but it has become too much of a spaghetti. The requirements are that there should always be one connection if possible in available state, but I need to take all the available states down and re-create them.
these paths I have to cover:
if both vifs down, call create
if both vifs available, take them down and up one-by-one
if one down and one available, bring first up the down one, then take down and bring up the available one
if only one down, get it up, then create the second one
if only one up, create the second one, then delete and re-create the first one
var vifsMap = make(map[string][]*directconnect.VirtualInterface)
var vifsStateAvailable, vifsStateDown []*directconnect.VirtualInterface
for _, item := range convertToDirectconnect(lagPair, amz.dcLags) {
vis, err := amz.dcRead.DescribeVirtualInterfaces(&directconnect.DescribeVirtualInterfacesInput{ConnectionId: item.LagId})
if err != nil {
return err
}
for _, vi := range vis.VirtualInterfaces {
if *vi.OwnerAccount == cfg.RemoteAccountID {
if aws.StringValue(vi.VirtualInterfaceState) == directconnect.VirtualInterfaceStateAvailable {
vifsStateAvailable = append(vifsStateAvailable, vi)
} else if aws.StringValue(vi.VirtualInterfaceState) == directconnect.VirtualInterfaceStateDown {
vifsStateDown = append(vifsStateDown, vi)
}
}
}
}
vifsMap["available"] = vifsStateAvailable
vifsMap["down"] = vifsStateDown
if len(vifsStateDown) > 1 {
fmt.Println("contains 2 down elements")
} else if len(vifsStateAvailable) > 1 {
fmt.Println("contains 2 up elements")
} else if len(vifsStateDown) == 1 && len(vifsStateAvailable) == 1 {
fmt.Println("contains 1 vif down and 1 up")
} else if len(vifsStateAvailable) == 1 && len(vifsStateDown) == 1 {
fmt.Println("contains 1 vif up and 1 down")
} else if len(vifsStateDown) == 1 && len(vifsStateAvailable) == 0 {
fmt.Println("contains 1 down only")
} else if len(vifsStateAvailable) == 1 && len(vifsStateDown) == 0 {
fmt.Println("contains 1 up only")
}

Remove ifs from Javascript code

Can i program without if statements in functional programming in JS?
In Haskell you can do pattern matching:
sign x | x > 0 = 1
| x == 0 = 0
in js:
sing = x => {
if (x > 0) return 1;
else if (x == 0) return 0
}
I can do shorthand if operator something like this:
sign = x => x > 0 ? 1 (x == 0 ? 0 : x)
Can I make the code shorter without library and ?: operator above ?
This might not be the answer your looking for but the shortest way to write this code is:
return !!x+0;
explanation
!!x casts x to a boolean: x>0 == true x = 0 == false;
+0 casts to integer: true = 1, false = 0.
But no there is no other style than using ?: operator.
javascript shorthand usefullness
In javascript you have other helpful tricks like:
Automatically casting things to thruties or falsies. (when boolean required)
Or operator returning the value, easy for null coalescing: var name = null || 'joel' // name = 'joel'

Chain across the matrix

Given a binary matrix, we want to check if there exists a path across nodes on two ends, such as:
0 1 0 0 0
0 1 1 0 0
0 0 1 1 0
0 0 0 1 0
this case has a chain of one's from the first to the last row which is stretched over in some of the rows. Similarly, the result should be true even if there's a chain from left to the right column.
I thought about writing a recursively exploring function for each positive element through-out the top row and the left column. Could you suggest something better?
one of solutions would be to use Set:
Go through each row
If field value is 1 and one of its already visited neighbours is inside the Set, add its coordinates (x,y) to the Set
At the end, check if Set contains any coordinates from the last row - if so, there is a path.
as you didn't mention which language you would like to use, here's how it looks like in Javascript (ES6):
let matrix = '01000
01100
00110
00010'.split('\n').map((row) => { return row.split('') });
let set = new Set();
let cols = matrix[0].length;
let rows = matrix.length;
for(let col=0; col < cols; col++){
if(matrix[0][col] == '1'){
set.add(`0,{col}`);
}
}
for(let row=1; row < rows-1; row++){
for(let col=1; col < cols; col++){
if(matrix[row][col] == '1' &&
(set.has(`{row-1},{col-1}`) ||
set.has(`{row-1},{col}`) ||
set.has(`{row-1},{col+1}`) ||
set.has(`{row},{col-1}`))){
set.add(`{row},{col}`);
}
}
}
let row = rows-1;
for(let col=0; col < cols; col++){
if(matrix[row][col] == '1' &&
(set.has(`{row-1},{col-1}`) ||
set.has(`{row-1},{col}`) ||
set.has(`{row-1},{col+1}`) ||
set.has(`{row},{col-1}`))){
// HAS PATH
}
}

Infinite loop (do - while)

for(int m=0;m<=3;m++){
for(int n=0;n<=3;n++){
if(n>0){
int c =n,t=1;
do{
t = up_key_no0(&puzz[c][m]);
c--;
}while(t==1||c>=0);
}
}
}
int up_key_no0(int *puzy){
int *puzx = puzy -4;
int down = *puzy;
int up = *puzx;
if(((down==up)||(up==0))&&down!=0){
*puzx += *puzy;
*puzy=0;
return 1;
}
else{
return 0;
}
}
Is The Following piece of code wrong? if Yes Then Reply. The Whole Code Cant Be Fit But puzz is a 2 dimensional array of 4X4
Your do-while loop can go out of the range of the table to the negative indices when the t is 1 and the c is 0. So maybe you should change the condition to (t == 1 && c >= 0) (and instead of or).
I don't know that language is this, but case it's like Java, a "for" should be like so:
for (var i=0;i<=3;i++) {
}
Your while maybe wrong. This "==" on the while should be "=".
while(t=1||c>=0) {
}

detect 4 permutations of 2 variable values in a switch case statement

I have 2 variables, width and height as integers. Any of these can be positive or negative (not zero). So naturally there are 4 cases;
width > 0 && height > 0
width > 0 && height < 0
width < 0 && height > 0
width < 0 && height < 0
Now I want to take different action on each of these 4 cases without using 4 if statements.
Is there a way to aggregate these cases so that it can be put as a simple switch case
switch( aggregate ){
case 1:
case 2:
case 3:
case 4:
}
If there is no better way than using if for each then in 3D space you have 3 lengths (x,y,z) and there will be 27 if blocks.
I'm using javascript if that matters.
In javascript this is quite easy, just turn the condition upside down:
switch(true)
{
case (width > 0 && height > 0):
break;
case (width > 0 && height < 0):
break;
case (width < 0 && height > 0):
break;
case (width < 0 && height < 0):
break;
default:
}
This also works in VB6/VBA but not in many other languaguages like C++ and C#.
Here's a simple proof: http://jsfiddle.net/avuxj/
You could treat each of your conditions (width positive, height positive) as a single boolean attribute and combine them to binary number and switch over it.
Pseudocode:
int v = (width > 0 ? 0 : 1) << 1 | (height > 0 ? 0 : 1) << 0;
switch (v) {
case 0b00:
// width < 0 && height < 0;
break;
case 0b01:
// width < 0 && height > 0;
break;
case 0b10:
// width > 0 && height < 0
break;
case 0b11:
// width > 0 && height > 0
break;
}
If the language of your choice doesn't have binary numeric literals, then it's not as readable, but you might be able to fix that with comments.
Also note that languages that support interpreting true as 1 and false as 0 will help make the int v = ... line shorter.
You could do
var bits=0;
if(width > 0) {
bits+=1;
}
if(height > 0) {
bits+=2;
}
switch{bits} {
case 0: //both negative
//something
break;
case 1: //width positive, height negative
//something
break;
case 2: //width negative, height positive
//something
break;
case 3: //both positive
//something
break;
}
Although it is all bit confusing. (Especially if You have 3 values). You can use variables to make Your code bit clearer.
var WIDTH_POSITIVE_BIT=1;
var HEIGHT_POSITIVE_BIT=2;
var bits=0;
if(width > 0) {
bits+=WIDTH_POSITIVE_BIT;
}
if(height > 0) {
bits+=HEIGHT_POSITIVE_BIT;
}
switch{bits} {
case 0: //both negative
//something
break;
case WIDTH_POSITIVE_BIT: //width positive, height negative
//something
break;
case HEIGHT_POSITIVE_BIT: //width negative, height positive
//something
break;
case WIDTH_POSITIVE_BIT+HEIGHT_POSITIVE_BIT: //both positive
//something
break;
}
I'd say that this does not help to make the code much clearer.
Can't do this without adding a little overhead.
s = ( width < 0 ) ? 0 : 1;
s += ( height < 0 ) ? 0 : 2;
switch(s) {
case 0: // 00 => both < 0
case 1: // 01 => width > 0, height < 0
case 2: // 10 => width < 0, height > 0
case 3: // 11 => both > 0
}
And this could work for a 3D case:
s = ( width < 0 ) ? 0 : 1; //First bit for width
s += ( height < 0 ) ? 0 : 2; //Second bit for height
s += ( depth < 0 ) ? 0 : 4; //Third bit for depth
switch(s) {
case 0: // 0 0 0
case 1: // 0 0 1
case 2: // 0 1 0
case 3: // 0 1 1
case 4: // 1 0 0
case 5: // 1 0 1
case 6: // 1 1 0
case 7: // 1 1 1
}
Of course assuming you can't have a 0 dimension.
Several answers are logically correct. If you were doing this in C it would be:
s = ((width<0)<<1) | (height<0);
switch(s) {
....
}
This can make a huge difference. I have code that combines 9 conditions into a switch like this. The switch gets turned into a jump table and is much faster than evaluating a bunch of conditions. There is no branching, just the jump table. I can't really speak to anything java or java script though.
You may also do nested if statements:
if (witdh<0) {
if (height<0) {
// both negative
}
else {
// only width negative
}
}
else {
if (height<0) {
// only height negative
}
else {
// both positive
}
}
I find mashing the condition bits together and using a switch to be more readable - especially if the number of conditions grows.

Resources