Calling sort after map on a array - d

I want to sort lines read from stdin by line length, after trimming white spaces off. The code works as expected.
import std.algorithm, std.array, std.stdio, std.string;
void main()
{
stdin
.byLineCopy
.map!(strip)
.array
.sort!((a, b) => a.length < b.length)
.each!writeln;
}
However, if I swap map line with array line,
void main()
{
stdin
.byLineCopy
.array
.map!(strip)
.sort!((a, b) => a.length < b.length)
.each!writeln;
}
The program fails to compile, with the following error,
sort_lines.d(9): Error: template std.algorithm.sorting.sort cannot deduce function from argument types !((a, b) => a.length < b.length)(MapResult!(strip, string[])), candidates are:
/usr/include/dmd/phobos/std/algorithm/sorting.d(1852): std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)
Failed: ["/usr/bin/dmd", "-v", "-o-", "sort_lines.d", "-I."]
I cannot understand why. Doesn't map function applies to each element in a range and return a new range? According to documentation, sort requires its range argument to be random-accessible. Is it the reason? If so, what is the type of the range returned by map?

map returns a range that does not have assignable or swappable elements - another requirement that sort specifies. The solution is, as in your first example, to iterate to an array first.
The elements are not assignable because map does computation and does not return a value by ref. Thus, even if you did grab the address of the returned element, and overwrote that with the new value for that position, it wouldn't change the value in the actual backing array.
The problem is actually slightly worse than this. What [1,2,3].map!(a => a * 2) does is it takes an element from [1,2,3] and multiplies it by 2. If I did something like [1,2,3].map!(a => a * 2)[0] = 4, that would have to invert the function a => a * 2 to figure out the value to put into [1,2,3], and turn it into [2,2,3]. In the above case that's relatively easy, but what if I tried to assign 5 instead of 4? What if the mapping function is a one-way hash? As we can see, the only real solution is a store with the mapped values - i.e. [1,2,3].map.array.

Related

How can I check if two cells are equal in brainf*ck?

How can I check if the value in cell #0 is equal to the value in cell #1? I am trying to write code equivalent to:
if(a == b)
{
//do stuff
}
else
{
//do something else
}
I have read Brainfuck compare 2 numbers as greater than or less than, and the second answer gave me a general idea of what I'd need to do, but I cannot figure it out. (That solution gives if a < b, else.)
I am thinking I need to do something along the lines of decrementing both values, and if they reach 0 at the same time, then they are true. But I keep getting stuck at the same exit point every time I think about it.
How can I check if two cells are equal in brainfuck?
I think I have it, I'm not a brainfuck expert but this question looked interesting. There might be a simpler way to do it, but I went with your method of decrementing values one by one.
In this case, if the two values in cell 0 and 1 are equal jump a ton forward, if they are not equal jump a little forward (second brackets is the not equal case, third brackets is the equal case)
Note that I'm using brainfucks while statements as a ghetto if (cell != 0)
+++++++++++++++++
>
+++++++++++++++++
>+<
[ - < - >] <[>>>>>] >> [>>>>>>>>>>>>>>>>>>>>>]
Try it online: http://fatiherikli.github.io/brainfuck-visualizer/#KysrKysrKysrKysrKysrKysKPgorKysrKysrKysrKysrKysrKwo+KzwKWyAtIDwgLSA+XSA8Wz4+Pj4+XSA+PiBbPj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+XQoKCg==
An example implementation, print T (true) if the two values are equal, F (false) if they are not equal
http://fatiherikli.github.io/brainfuck-visualizer/#KysrCj4KKysrKwo+KzwKWyAtIDwgLSA+XSA8Wz4+PgorKysrKysrKysrKysrKysrKysrKworKysrKysrKysrKysrKysrKysrKworKysrKysrKysrKysrKysrKysrKworKysrKysrKysrCi4KPgoKXSA+PiBbCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKwouCj4KXQ==
+>>(a+++++)>(b+++++)>>+<<<
[[->]<<]
<
[>>>>>-<<<<<
a>b
]
>>
[->>-<
a<b
]
>>
[-
a=b
]
Pointer ends on the same pointer in the same state but the code within the appropriate brackets has been executed.
I came up with this for my bf compiler thing
basically it subtracts and then checks if the result is 0.
Can be easily changed to execute stuff in if/else-ish way
Layout:
[A] B
>[-<->]+<[>-<[-]]>
Output
0 [result]
Result is 1 if equal

error : Vector subscript out of range error

I have this code in c++ and I used vectors but I got this error:
error: Vector subscript out of range error.
Can some help me in this issue.
int const TN = 4;
vector <uint32_t> totalBytesReceived(TN);
void ReceivePacket(string context, Ptr <const Packet> p)
{
totalBytesReceived[context.at(10)] += p->GetSize();
}
void CalculateThroughput()
{
double mbs[TN];
for (int f = 0; f<TN; f++)
{
// mbs = ((totalBytesReceived*8.0)/100000);
mbs[f] = ((totalBytesReceived[f] * 8.0) / 100000);
//totalBytesReceived =0;
rdTrace << Simulator::Now().GetSeconds() << "\t" << mbs[f] << "\n";
Simulator::Schedule(Seconds(0.1), &CalculateThroughput);
}
}
It seems like
totalBytesReceived[context.at(10)] += p->GetSize();
throws the exception because the char at position 10 of context is out of range. Since you use it to index the vector, it has to be in the range 0 to 3.
Looking at the content of context you posted:
"/NodeList/" 1 "/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx"
^ ^ ^
0 10 12
If you want to extract the 1 and use it as an index, you need to use:
char c = context.at(12); // Extract the char.
int index = c - '0'; // Convert the character '1' to the integer 1.
This is because of the ASCII standard which determines how characters are stored as numbers.
Probably the real issue is that you get the character '1' and use its ASCII value as index to the vector instead of the intended integer value 1.
This out of bounds access is then undefined behaviour, which in your case leads to an exception.
The following is not the cause, leaving it for reference:
The exception is probably coming from this expression:
context.at(10)
This is the only operation (*) involved that is actually performing bounds checking. The vector operator[] isn't doing that, neither does a C array check it's bounds.
So: Are you sure the string context is never shorter than 11 characters?
(*) Accessing a vector out of bounds is undefined behaviour, and throwing an exception is within the possible outcomes of that. Thanks to Beta Carotin and Benjamin Lindley for that.
This is the real thing:
Also note that a vector isn't resized like map when accessing an out of bounds index using operator[], so unless you can guarantee that the characters in the string are between 0 and 3 inclusive this will be your next issue.
And this means (size_t)0 and (size_t)3, not the characters '0' and '3'.

strange case of assigning string to a variable in c++

1. vector<string> cmdv=explode(" ","i am a string");
2. std::string arg;
3. char * args[10];
4. for (i = 0; i < cmdv.size(); i++) {
5. arg = std::string(cmdv[i]);
6. if (cmdv[i][0] == '"') {
7. //do some thing
8. }
9. args[i] = arg.c_str();;
10. }
11. args[i]='\0';
I expected the contents of args array {"i","am","a","string"} but args array is {"am","a","string","string"}
on debug i found that at line 6 in if clause when cmdv[i][0] is compared with '"', args[i-1] is being replaced with contents of arg. I got baffled!
there is no problem with explode function. Its working good.
This is a problem :-
args[i] = arg.c_str();
The pointer returned by this is only valid while arg contains it's value and you alter arg each time through your loop. If you want to store a C style pointer to the string you'll need to make a copy of it, maybe something like :-
args[i] = strdup(arg.c_str());
But remember to free it. Plus there is probably a better way to achive what you want than using C style strings anyway

Trying to make a recursive call in C++

This is my first question here so be kind :-) I'm trying to make a recursive call here, but I get the following compiler error:
In file included from hw2.cpp:11:
number.h: In member function ‘std::string Number::get_bin()’:
number.h:60: error: no matching function for call to ‘Number::get_bin(int&)’
number.h:27: note: candidates are: std::string Number::get_bin()
string get_bin ()
{
bin = "";
printf("Value is %i\n",val);
if (val > 0)
{
int remainder = val;
printf("remainder is %i\n",remainder);
printf("numbits is %i\n",size);
for (int numbits = size-1;numbits>=0;numbits--)
{
//printf("2 raised to the %i is %i\n",numbits,int(pow(2,numbits)));
printf("is %i less than or equal to %i\n",int(pow(2,numbits)),remainder);
if (int (pow(2,numbits))<=remainder)
{
bin+="1";
remainder -= int(pow(2,numbits));
printf("Remainder set to equal %i\n",remainder);
}
else
{
bin+= "0";
}
}
return bin;
}
else
{
int twoscompliment = val + int(pow(2,size));
return get_bin(twoscompliment);
}
Any thoughts? I know get_bin works for positive numbers.
In the last line you are calling get_bin() with an integer reference argument, but there are no formal parameters in the function signature.
string get_bin ()
return get_bin(twoscompliment);
These are mutually incompatible. I don't see how you can say that code works for positive numbers since it's not even compiling.
You probably need to change the first line to something like:
string get_bin (int x)
but, since you don't actually use the argument, you may have other problems.
If you're using global or object-level variables to do this work, recursion is not going to work, since they different levels will be stepping on each other's feet (unless you do your own stack).
One of the beauties of recursion is that your code can be small and elegant but using local variables is vital to ensure your data is level-specific.
By way of example, examine the following (badly written) pseudo-code:
global product
def factorial (n):
if n == 1:
return 1
product = factorial (n-1)
return n * product
Now that won't work for factorial (7) since product will be corrupted by lower levels. However, something like:
def factorial (n):
local product
if n == 1:
return 1
product = factorial (n-1)
return n * product
will work just fine as each level gets its own copy of product to play with. Of course:
def factorial (n):
if n == 1:
return 1
return n * factorial (n-1)
would be even better.
The function is defined to take no arguments, yet you pass an int.
It looks like you're accessing a global or member variable val. That should probably be converted into the argument.
string get_bin ( int val )
Since you have not declared bin and val in the function I guess they are global.
Now you define the function get_bin() to return a string and not accept anything. But in the recursive call you are passing it an int. Since you want to pass twoscompliment as val for the recursive call you can do:
int twoscompliment = val + int(pow(2,size));
val = twoscompliment; // assign twoscompliment to val
return get_bin();

Compare a value with all array elements in one statement

For example:
if (value == array[size]) //if the value (unique) is present in an array then do something
can this be done in one statement without having to call a function or a basic for loop statement?
std::find can do it in one statement, but it's not as trivial as other languages :(
int array[10];
if (array + 10 != find(array, array + 10, 7)) {
cout << "Array contains 7!";
}
Or with std::count:
if (int n = count(array, array + 10, 7)) {
cout << "Array contains " << n << " 7s!";
}
Depending on the problem, you might want to use a set. It has a member function called count() that tells you if something is in the set:
if(myset.count(value) > 0){
doThings();
}
There is no built-in operator to do such a thing.
There are numerous ways to perform the test as what appears to be a single statement from the outside. And some of which use parts already provided by the standard library, so that you wouldn't have to write much code yourself. However, they will inevitably use some form of function call and/or loop at some point which you already ruled out.
So given the restrictions in your question: No, there isn't any way.