Standard ML binary tree datatype - binary-tree

I know this question has been asked before, but none of the answers in previous questions worked for me so I'll try a different approach.
I've done this:
> datatype which = STRING of string | INT of int;
datatype which = INT of int | STRING of string
> datatype whichTree = Empty | Leaf of which | Node of whichTree*whichTree;
datatype whichTree = Empty | Leaf of which | Node of whichTree * whichTree
but when I try to build a tree
> val mytree = Node(Leaf(which 2), Leaf(which 6));
I get errors.
Error-Value or constructor (which) has not been declared Found near
Node( Leaf(which(2)), Leaf(which(6)))
Error-Value or constructor (which) has not been declared Found near
Node( Leaf(which(2)), Leaf(which(6)))
Static errors (pass2)

which is the name of the datatype; it's not a constructor. Instead, you have to create a tree as follows:
> val mytree = Node(Leaf(INT 2), Leaf(STRING "6"));

Related

Getting the Shorest Path question right in Kotlin

So I got a question that was delivered as a 2D List
val SPE = listOf(
listOf('w', 'x'),
listOf('x', 'y'),
listOf('z', 'y'),
listOf('z', 'v'),
listOf('w', 'v')
)
It asks to find the shortest path between w and z. So obviously, BFS would be the best course of action here to find that path the fastest. Here's my code for it
fun shortestPath(edges: List<List<Char>>, root: Char, destination: Char): Int {
val graph = buildGraph3(edges)
val visited = hashSetOf(root)
val queue = mutableListOf(mutableListOf(root, 0))
while (queue.size > 0){
val node = queue[0].removeFirst()
val distance = queue[0].removeAt(1)
if (node == destination) return distance as Int
graph[node]!!.forEach{
if (!visited.contains(it)){
visited.add(it)
queue.add(mutableListOf(it, distance + 1))
}
}
}
queue.sortedByDescending { it.size }
return queue[0][1]
}
fun buildGraph3(edges: List<List<Char>>): HashMap<Char, MutableList<Char>> {
val graph = HashMap<Char, MutableList<Char>>()
for (i in edges.indices){
for (n in 0 until edges[i].size){
var a = edges[i][0]
var b = edges[i][1]
if (!graph.containsKey(a)) { graph[a] = mutableListOf() }
if (!graph.containsKey(b)) { graph[b] = mutableListOf() }
graph[a]?.add(b)
graph[b]?.add(b)
}
}
return graph
}
I am stuck on the return part. I wanted to use a list to keep track of the incrementation of the char, but it wont let me return the number. I could have done this wrong, so any help is appreciated. Thanks.
If I paste your code into an editor I get this warning on your return queue[0][1] statement:
Type mismatch: inferred type is {Comparable<*> & java.io.Serializable} but Int was expected
The problem here is queue contains lists that hold Chars and Int distances, mixed together. You haven't specified the type that list holds, so Kotlin has to infer it from the types of the things you've put in the list. The most general type that covers both is Any?, but the compiler tries to be as specific as it can, inferring the most specific type that covers both Char and Int.
In this case, that's Comparable<*> & java.io.Serializable. So when you pull an item out with queue[0][1], the value you get is a Comparable<*> & java.io.Serializable, not an Int, which is what your function is supposed to be returning.
You can "fix" this by casting - since you know how your list is meant to be organised, two elements with a Char then an Int, you can provide that information to the compiler, since it has no idea what you're doing beyond what it can infer:
val node = queue[0].removeFirst() as Char
val distance = queue[0].removeAt(1) as Int
...
return queue[0][1] as Int
But ideally you'd be using the type system to create some structure around your data, so the compiler knows exactly what everything is. The most simple, generic one of these is a Pair (or a Triple if you need 3 elements):
val queue = mutableListOf(Pair<Char, Int>(root, 0))
// or if you don't want to explicitly specify the type
val queue = mutableListOf(root to 0)
Now the type system knows that the items in your queue are Pairs where the first element is a Char, and the second is an Int. No need to cast anything, and it will be able to help you as you try to work with that data, and tell you if you're doing the wrong thing.
It might be better to make actual classes that reflect your data, e.g.
data class Step(node: Char, distance: Int)
because a Pair is pretty general, but it's up to you. You can pull the data out of it like this:
val node = queue[0].first
val distance = queue[0].second
// or use destructuring to assign the components to multiple variables at once
val (node, distance) = queue[0]
If you make those changes, you'll have to rework some of your algorithm - but you'll have to do that anyway, it's broken in a few ways. I'll just give you some pointers:
your return queue[0][1] line can only be reached when queue is empty
queue[0].removeAt(1) is happening on a list that now has 1 element (i.e. at index 0)
don't you need to remove items from your queue instead?
when building your graph, you call add(b) twice
try printing your graph, the queue at each stage in the loop etc to see what's happening! Make sure it's doing what you expect. Comment out any code that doesn't work so you can make sure the stuff that runs before that is working.
Good luck with it! Hopefully once you get your types sorted out things will start to fall into place more easily

How is the | symbol read in Elm?

Consider the following example code:
-- Update the fields of a record. (It must have the fields already.)
{ person |
name = "George" }
-- Update multiple fields at once, using the current values.
{ particle |
position = particle.position + particle.velocity,
velocity = particle.velocity + particle.acceleration }
Source: Learn Elm in X Minutes
How is one supposed to read | in this example, and in Elm generally?
I'm familiar with it in set-builder notation as "where" / "such that", and in list comprehensions in Haskell it has a very similar purpose, e.g.
[ x*2 | x <- [1..10] ]
is logically equivalent to
source: Learn You A Haskell
(Obviously I'm also familiar with its use as the unary "or" operator in C-like languages)
What about something like type Msg = Increment | Decrement ?
Source: https://guide.elm-lang.org
Or, in this example when discussing Union Types:
type Boolean
= T
| F
| Not Boolean
| And Boolean Boolean
| Or Boolean Boolean
In types I read it as 'or'. In the counter example:
type Msg = Increment | Decrement
I would read it as "a Msg is Increment or Decrement". In a slightly more complex but still common example of the Result type:
type Result error value
= Ok value
| Err error
I would read "a Result is either Ok with a value or Err with an error".
In the example you give of the record update syntax, I would read it as 'with' rather than 'where'. For example:
{ person | name = "George" }
is "the person value with its name field set to "George"" (rather than "where the name = 'George'" which seems to imply that you're filtering based on what values are in person). This one is I think more ambiguous than the type case though.

i want to create generic list from string

i want to create generic list from string
input string is (a(b,c,u),d,e(f),g(),h,i(j(k,l,m(n))),r)
my class is
public class Node
{
public string Name; // method name
// public decimal Time; // time spent in method
public List<Node> Children;
}
child node is represent in ().
Example: a is parent node and b,c u are child nodes; will be saved in List<Node> in the same way as its parent which has j as child and k,l and m as children j.
it is similary like tree
<.>
|---<a>
| |--- b
| |--- c
| |--- u
|--- d
|---<e>
| |--- f
|---<g>
|--- h
|---<i>
| |---<j>
| | |--- k
| | |--- l
| | |---<m>
| | | |--- n
|--- r
The end result for you Node data structure will end up looking similar to a tree. To achieve what you want you could use a recursive function.
Here is an example of such a function (with comments):
//Recursive Function that creates a list of Node objects and their
//children from an input string
//Returns: List of Nodes
//Param string input: The input string used to generate the List
//Param int index: The index to start looping through the string
public List<Node> CreateNodeList(string input, int index)
{
List<Node> nodeList = new List<Node>();
Node currentNode = new Node();
StringBuilder nameBuilder = new StringBuilder();
//Start looping through the characters in the string at the
//specified index
for(int i = index; i < array.size; i++)
{
switch(input[i])
{
//If we see an open bracket we need to use the
//proceeding list to create the current nodes children
//We do this by recursively calling this function
//(passing the input string and the next index as
//parameters) and setting the children property to b
//the return value
case ‘(‘:
currentNode.Children = CreateNodeList(input, i+1);
i = input.IndexOf(‘)’, i);
break;
//If we see a closed bracket we create a new Node based
//of the existing string, add it to the list, and then
//return the list
case ‘)’:
currentNode.Name = nameBuilder.ToString();
nodeList.Add(currentNode);
nameBuilder.Clear();
return nodeList;
//if we see a comma we create a new node object based
//off the current string and add it to the list
case ‘,’:
currentNode.Name = nameBuilder.ToString();
nodeList.Add(currentNode);
nameBuilder.Clear();
currentNode = new Node();
break;
//Any other character we see must be for the name
//of a node, so we will append it to our string
//builder and continue looping
default:
nameBuilder.Append(input[i]);
}
}
//We will probably never reach here since your input string
//usually ends in ‘)’ but just in case we finish by returning
//the list
return nodeList;
}
//An example of how to use this recursive function
public static void main()
{
//Your input string
string input = “(a(b,c,u),d,e(f),g(),h,i(j(k,l,m(n))),r)”;
//Call our function with the input string and 1 as arguments
//We use 1 to skip the first ‘(‘ which is a index 0
List<Node> nodeList = CreateNodeList(input, 1);
//Do stuff with list here
}
This function keeps track of characters for the names of nodes, creating new ones and adding them to the list every time it sees a ',' or ')' (returning the List when seeing a ')')) and it also populates a Nodes children when it sees a '(' character by recursively calling the function and using its return value. The one major downside being you have keep track off the index you're on.
This function was written free hand but it's meant to be very similiar to C# (you didn't specify a language so I hope this helps.)
I hope this helps and is what your'e looking for :)

How to parse a certain type of configuration file

Recently I encounter an interview question. I was required to write code for expression evaluation. The expression format looks like this:
B=10;
A={
A=100;
B=BDE;
C=C;
D={
A=windows;
B=mac;
C={
A=redhat;
B=ubuntu;
};
};
A+={
A=200;
E=1000;
};
To represent the key of the expression, period delimitated method is used. For example, A.B represents the element B in Map A, and the value of A.B is BDE; similarly, the value of A.D.C.A is redhat. the the represent string is called 'path expression'.
the configuration also support append and override operation. for the above example, we use += operation to append or override the value in Map A. now the value of A.A is 200, and the value of A.E is 1000;
Now, given a configuration strings and the key path of configuration, I was required to return the value of configuration based the configuration strings.
Rules
1) the key name and his value only contains alphabet(A-Z,a-z) and number(0-9), no other characters;
2) if cannot find the value or the expression point to a map, please output "N/A"
3) if find the value, please output the value. no spaces when output the value.
Input and Output
there are three part sin the input. the first line contains two integers indicates the number of congiruation lines(M) and the number of expressions(N).
M<=100, N<=100. the following M lines are the confugration and the last N lines are expression. every configuration line contains one or more configurations. every line length less than 1000.
Input :
2 2
A={A=1;B=2;C=3;E={A=100;};};
A+={D=4;E={B=10;C=D;};};
A.E.B
B.D.E
Output
A.E.B=10
B.D.E=N/A
My thoughts
I was thinking about using a N-nary tree to represent the expression. For example, the expression: A = {A = 1;D = 1;B = {C = 1,D = {D = 1,F = 2};};}; can be represented as:
(A,-)
/ | \
(A,1) (D,1) (B,-)
/ \
(C,1) (D,-)
/ \
(D,1) (F,2)
Since a N-nary tree can be represented as a binary tree. Thus, all append or search operations would be either the insert or search operations for a binary tree. It seems that this approach works. But I am wondering if there is a better way to approach this problem?
I am thinking about putting all children in a hash map (since that's what interviewers like)
Node{
String val;
HashMap<String, Node> children;
Node(int val){
this.val = val;
children = new HashMap<String, Node>();
}
}

HowTo sort std::map by first and second params?

Here is my std::map example, like std::map< string, string > my_map;
// ABC | aaa ABC | aaa
// DEF | def ABC | dcd
// BCD | def -> ABC | zzz
// DEF | bcd BCD | def
// ABC | dcd DEF | bcd
// ABC | zzz DEF | def
As you can see, I'm trying to sort left std::map and get the right one.
And here is my code (I used not strings, but my custom types. any way, in final, I'm sorting strings):
template < typename T1, typename T2 >
struct less_second
{
typedef std::pair< T1, T2 > type;
bool operator ()( type const& _left, type const& _right ) const
{
return ( (*_left.first).name() < (*_right.first).name() ) &&
( (*_left.second).name() < (*_right.second).name() );
}
};
Problem: when I use only in less_second
return (*_left.first).name() < (*_right.first).name();
All data from the first column sorted, but second column not (of course, because we are used only first!)
The mirrored situation, when I use only
return (*_left.second).name() < (*_right.second).name();
The second column sorted.
BUT I need to sort and first and the second columns at once. How to code this? What I'm doing wrong?
Thanks for help!
Sorry, forget this code:
std::vector< std::pair< CompanyPtr, ContractorPtr > > n_map_( buddies_ccm_.begin(), buddies_ccm_.end() );
std::sort( n_map_.begin(), n_map_.end(), less_second< CompanyPtr, ContractorPtr >() );
Your comparison function is wrong. It does not work when both first.name() are equal. Try something like this:
bool operator ()( type const& _left, type const& _right ) const
{
if ((*_left.first).name() > (*_right.first).name())
return false;
if ((*_left.first).name() < (*_right.first).name())
return true;
return ( (*_left.second).name() < (*_right.second).name() );
}
I'm a little bit confused by the term "columns". Are you talking about keys and values?
A std::map is always ordered by key. You can specify a compare object at construction time of your map to define that order. But this compare object does not compare std::pairs, but objects of the key type of your map.
Moreover, a key in a map is unique. Thus, there cannot be two entries with the key "ABC" in the map.
I suppose you try to sort the map with std::sort from <algorithm>. I'm not sure what happens in this case, but I think it is not what you expect to happen.
You only want to take the second column into account if _left->first and _right->first are equal. Put another way, you want to make your code compare the first fields first, and fall back to comparing the second fields only if the first comparison is inconclusive (which happens when both firsts are equal).
You cannot achieve what you want with a std::map as it has been already explained in another answer. If your pairs don't have repetitions you could use a set of pairs:
std::set<std::pair<std::string, std::string> > pair_set;
You don't need to provide a comparator as std::pair already supports the kind of comparison you require.

Resources