X++ switch case with multiple inputs - axapta

Is there a way like in C# to create a switch with multiple variables?
something like this..
switch((_dim1,_dim2,_dim3))
{
case(1, ""):
Info("1 is null");
case (2, ""):
Info("2 is null");
case (3, ""):
break;
}

Switch with multiple arguments have been possible since version 1.0 (+23 years).
It requires the use of containers.
There is no dont-care value.
The following job demonstrates:
static void TestConSwitch(Args _args)
{
int dim1 = 2;
str dim2 = '';
switch ([dim1, dim2])
{
case [1, '']:
info("Case 1");
break;
case [2, '']:
info("Case 2");
break;
default:
info("Default!");
}
}
In this case displays "Case 2".
That said, performance of this may not be great, as it requires the build of containers for both the target value and all the case values (if no match).
Looks kind of neat though.

This is not possible in x++, as there is no tuple pattern as in c#-8.0.
Edit: As #Jan B. Kjeldsen shows in his answer, x++ containers can be used similar to how tuple patterns can be used in c#-8.0 to create a switch statement with multiple inputs.

Related

What is an elegant way to break out of a visit statement in Rascal MPL?

I'm using visit in rascal to iterate through a string. I would like to break out once I match a specific case. In other words, I would like to achieve this exact behavior:
str toVisit = "abcdefgh";
while(true) {
visit(toVisit) {
case /^bc/: println("before");
case /^de/: break;
case /^fg/: println("after");
}
break;
}
but without the while loop. There is no mention of this in the manual page of visit. Hence my question: is there an elegant way to break out of a visit statement in Rascal MPL?
visit is general better at recursive traversals then iterating, but return is the typical way people do break out of visits:
void myFunction() {
visit (toVisit) {
case /^bc/: println("before");
case /^de/: return;
case /^fg/: println("after");
}
}
So that favors smaller functions :-)
Otherwise, regular expressions themselves have excellent backtracking behavior for searching linear patterns like that:
for (/<before:.*>bc<middle:.*>de<after:.*>fg/ := "abcdefgh") {
println("match! <before> <middle> <after>");
// fail brings you to the next match (also for visit, if, etc)
fail;
// break jumps out of the loop
break;
// continue brings you to the next match as well
continue;
}

Convert A Given Binary Tree To Doubly Linked List

The problem statement is:
Given a Binary Tree, convert this binary tree to a Doubly Linked List.
A Binary Tree (BT) is a data structure in which each node has at most two children.
A Doubly Linked List contains a previous pointer, along with the next pointer and data.
The order of nodes in Doubly Linked List must be the same as Inorder of the given Binary Tree.
The doubly linked list should be returned by taking the next pointer as right and the previous pointer as left.
You need to return the head of the Doubly Linked List.
For example:
4
/ \
2 5
/ \
1 3
The doubly linked list would be: 1 2 3 4 5
My code is:
class BinaryTreeNode
{
public :
T data;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
BinaryTreeNode(T data) {
this -> data = data;
left = NULL;
right = NULL;
}
};
void inorder(BinaryTreeNode<int>* root,BinaryTreeNode<int>* &prev,BinaryTreeNode<int>* &nroot){
if(!root) return;
inorder(root->left,prev,nroot);
if(prev == NULL) nroot=root;
else{
root->left = prev;
prev->right=root;
}
prev=root;
inorder(root->right,prev,nroot);
}
BinaryTreeNode<int>* BTtoDLL(BinaryTreeNode<int>* root) {
BinaryTreeNode<int>* prev=NULL;
BinaryTreeNode<int>* nroot=NULL;
inorder(root,prev,nroot);
return nroot;
}
I have doubt regarding root.
The root pointer works with passing by value and does not works when it is passed by reference.
When root is passed by reference, it does not work.
void inorder(BinaryTreeNode<int>*& root,BinaryTreeNode<int>*& prev,BinaryTreeNode<int>* &nroot){
if(!root) return;
inorder(root->left,prev,nroot);
if(prev == NULL) nroot=root;
else{
root->left = prev;
prev->right=root;
}
prev=root;
inorder(root->right,prev,nroot);
}
How can I know which variable should be passed by reference and which variable should by passed by value with regard to pointers?
At first glance, one problem is the API of inorder itself. You are assigning nroot = root; to see why this is a problem, consider this simpler example:
void set_x(int *x, int *y)
{
x = y;
}
Remember that pointers are really just memory addresses. So, the assignment of x = y says, "replace the memory address that x contains, and set it to whatever y contains". At no stage do you actually change the value at the memory address.
Now, considering nroot = root again, here you are just giving the local variable you have a new memory address, but not updating anything. So at your call side BTtoDLL, you provide it nullptr for the address, to which it never uses it, and never sets it. So, BTtoDLL will never see any change to nroot.

How to output a multidimensional array slice

Let's say I have a multidimensional array:
logic [7:0] mda [7:0];
What I'm now trying to do, is assigning mda[7:4] to an output port, i.e. defined as follow:
output [31:0] odata;
Of course, I can do it by using concatenation:
assign odata = {mda[7], mda[6], mda[5], mda[4]};
But there should be (and probably is) an easier way to do this. The first try would be:
assign odata = mda[7:4];
which is wrong, because types (unpacked <-> packed array) don't match. All my tries of casting (e.g. 32'(mda[7:4])) failed. Question is: what is the best way to assign that slice to an output port?
You can use a for loop... Most synthesis tools have no trouble with for loops over constant ranges:
module dut(output [31:0] odata);
logic [7:0] mda [7:0];
reg[31:0] data;
always #* begin
data = 0;
for(int i=7; i >=4; i--) begin
data <<= 8;
data |= mda[i];
end
end
assign odata = data;
endmodule
Here's a quick test: http://www.edaplayground.com/x/GfM
You can use the streaming operator:
initial begin
logic[31:0] data;
mda[7] = 'hde;
mda[6] = 'had;
mda[5] = 'hbe;
mda[4] = 'hef;
data = { >> { mda[7:4] }};
$display("data = ", data);
end
This works perfectly in a procedural context, but not in a continuous assignment context (for some reason). This means this doesn't work:
assign odata = { >> { mda[7:4] }};
You'll have to figure out a workaround here where you do the streaming in a procedural context (maybe some always block) and then assign the result to your wire.

Backtracking recursively with multiple solutions

function BACKTRACKING-SEARCH(csp) returns a solution, or failure
return RECURSIVE- BACKTRACKING({ }, csp)
function RECURSIVE-BACKTRACKING(assignment,csp) returns a solution, or failure
if assignment is complete then
return assignment
var ←SELECT-UNASSIGNED-VARIABLE(VARIABLES[csp],assignment,csp)
for each value in ORDER-DOMAIN-VALUES(var,assignment,csp) do
if value is consistent with assignment according to CONSTRAINTS[csp] then
add {var = value} to assignment
result ← RECURSIVE-BACKTRACKING(assignment, csp)
if result ̸= failure then
return result
remove {var = value} from assignment
return failure
This is a backtracking recursion algorythm pseudocode from AIMA. However, I don't understand if it returns ALL possible solutions or just first one found. In case it is the last option, could you please help me modify it to return a list of possible solutions instead (or at least updating some global list).
EDIT: I implemented this algorithm in Java. However, there is one problem:
if I don't return assignment, but save it in result instead, the recursion stop condition fails (i.e. it doesn't exist anymore). How can I implement another stop-condition? Maybe I should return true in the end?
Here is my code :
/**
* The actual backtracking. Unfortunately, I don't have time to implement LCV or MCV,
* therefore it will be just ordinary variable-by-variable search.
* #param line
* #param onePossibleSituation
* #param result
*/
public static boolean recursiveBacktrack(Line line, ArrayList<Integer> onePossibleSituation, ArrayList<ArrayList<Integer>> result){
if (onePossibleSituation.size() == line.getNumOfVars()){
// instead of return(assignment)
ArrayList<Integer> situationCopy = new ArrayList<Integer>();
situationCopy.addAll(onePossibleSituation);
result.add(situationCopy);
onePossibleSituation.clear();
}
Block variableToAssign = null;
// iterate through all variables and choose one unassigned
for(int i = 0; i < line.getNumOfVars(); i++){
if(!line.getCspMiniTaskVariables().get(i).isAssigned()){
variableToAssign = line.getCspMiniTaskVariables().get(i);
break;
}
}
// for each domain value for given block
for (int i = line.getCspMiniTaskDomains().get(variableToAssign.getID())[0];
i <= line.getCspMiniTaskDomains().get(variableToAssign.getID())[0]; i++){
if(!areThereConflicts(line, onePossibleSituation)){
//complete the assignment
variableToAssign.setStartPositionTemporary(i);
variableToAssign.setAssigned(true);
onePossibleSituation.add(i);
//do backtracking
boolean isPossibleToPlaceIt = recursiveBacktrack(line,onePossibleSituation,result);
if(!isPossibleToPlaceIt){
return(false);
}
}
// unassign
variableToAssign.setStartPositionTemporary(-1);
variableToAssign.setAssigned(false);
onePossibleSituation.remove(i);
}
// end of backtracking
return(false);
}
This code checks if solution found and if it is, returns the solution. Otherwise, continue backtracking. That means, it returns the first solution found.
if result ̸= failure then
return result
remove {var = value} from assignment
You can modify it like that:
if result ̸= failure then
PRINT result // do not return, just save the result
remove {var = value} from assignment
Or, better, modify this part:
if assignment is complete then
print assignment
return assignment // print it and return
About edited question:
First, return true in the first if, so recursion will know that it found a solution. The second step, there is a mistake, probably:
if(!isPossibleToPlaceIt){
return(false);
}
Should be
if(isPossibleToPlaceIt){
return(true);
}
Because if your backtracking has found something, it returns true, which means you don't have to check anything else any longer.
EDIT#2: If you want to continue backtracking to find ALL solutions, just remove the whole previous if section with return:
//if(isPossibleToPlaceIt){
// return(true);
//}
So we will continue the search in any way.

How can I simply check if a set of n numbers are all different?

I have n integers and I need a quick logic test to see that they are all different, and I don't want to compare every combination to find a match...any ideas on a nice and elegant approach?
I don't care what programming language your idea is in, I can convert!
Use a set data structure if your language supports it, you might also look at keeping a hash table of seen elements.
In python you might try
seen={}
n_already_seen=n in seen
seen[n]=n
n_already_seen will be a boolean indicating if n has already been seen.
You don't have to check every combination thanks to commutivity and transitivity; you can simply go down the list and check each entry against each entry that comes after it. For example:
bool areElementsUnique( int[] arr ) {
for( int i=0; i<arr.Length-1; i++ ) {
for( int j=i+1; j<arr.Length; j++ ) {
if( arr[i] == arr[j] ) return false;
}
}
return true;
}
Note that the inner loop doesn't start from the beginning, but from the next element (i+1).
You can use a Hash Table or a Set type of data structure that using hashing. Then you can insert all of the elements into the hashtable or hashset, and either as you insert, check if the element is already in the table/set. If for some reason you don't want to check as you go, you can just insert all the numbers and then check to see if the size of the structure is less than n. If it is less than n, there had to be repeated elements. Otherwise, they were all unique.
Here is a really compact Java solution. The time-complexity is amortized O(n) and the space complexity is also O(n).
public boolean areAllElementsUnique(int [] list)
{
Set<Integer> set = new HashSet<Integer>();
for (int number: list)
if (set.contains(number))
return false;
else
set.add(number);
return true;
}

Resources