Compound assignment operators, what happens if the value is modified (in the meanwhile)? - language-agnostic

Consider the following pseudocode (language agnostic):
int f(reference int y) {
y++;
return 2;
}
int v = 1;
v += f(v);
When the function f changes y (that is v) while evaluating v += f(v), is the original value of v "frozen" and changes to v "lost"?
v += f(v); // Compute the address of v (l-value)
// Evaluate v (1)
// Execute f(v), which returns 2
// Store 1 + 2
printf(v); // 3

In most languages += operator (as well as any other compound assignment operator, as well as simple assignment operator) has right-to-left associativity. That means f(v) value will be evaluated first, then its result will be added to the current value of v.
So in your example it should be 4, not 3:
C++: (demo)
int f(int& v) {
v++;
return 2;
}
int main() {
int v = 1;
v += f(v);
cout << v; // 4
}
Perl: (demo)
sub f {
$_[0]++;
return 2;
}
my $v = 1;
$v += f($v);
print $v; # 4

Related

Implementing Dijkstra's algorithm with C++ STL

I have implemented the Dijkstra's algorithm as follows
#include <iostream>
#include <bits/stdc++.h>
#include<cstdio>
#define ll long long int
#define mod 1000000007
#define pi 3.141592653589793
#define f first
#define s second
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define vfor(e, a) for (vector<ll> :: iterator e = a.begin(); e != a.end(); e++)
#define vfind(a, e) find(a.begin(), a.end(), e)
#define forr(i, n) for (ll i = 0; i < n; i++)
#define rfor(i, n) for (ll i = n - 1; i >= 0; i--)
#define fors(i, b, e, steps) for(ll i = b; i < e; i += steps)
#define rfors(i, e, b, steps) for(ll i = e; i > b; i -= steps)
#define mp make_pair
using namespace std;
void up(pair<ll, ll> a[], ll n, ll i, ll indArray[]) {
ll ind = (i - 1) / 2;
while (ind >= 0 && a[ind].s > a[i].s) {
swap(a[ind], a[i]);
indArray[a[ind].f] = ind;
indArray[a[i].f] = i;
i = ind;
ind = (i - 1) / 2;
}
}
void down(pair<ll, ll> a[], ll n, ll i, ll indArray[]) {
ll left = 2 * i + 1;
ll right = 2 * i + 2;
ll m = a[i].s;
ll ind = i;
if (left < n && a[left].s < m) {
ind = left;
m = a[left].s;
}
if (right < n && a[right].s < m) {
ind = right;
}
if (ind != i) {
swap(a[i], a[ind]);
indArray[a[i].f] = i;
indArray[a[ind].f] = ind;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// cout << setprecision(10);
ll n, m;
cin >> n >> m;
vector<pair<ll, ll>> a[n];
forr(i, m) {
ll u, v, w;
cin >> u >> v >> w;
a[u].pb(mp(v, w));
a[v].pb(mp(u, w));
}
ll parent[n];
parent[0] = -1;
pair<ll, ll> dist[n];
forr(i, n) {
dist[i] = mp(i, INT_MAX);
}
dist[0].s = 0;
ll ind[n];
iota(ind, ind + n, 0);
ll ans[n];
ans[0] = 0;
bool visited[n];
fill(visited, visited + n, false);
ll size = n;
forr(i, n) {
ll u = dist[0].f;
visited[u] = true;
ll d1 = dist[0].s;
ans[u] = dist[0].s;
swap(dist[0], dist[size - 1]);
size--;
down(dist, size, 0, ind);
for (auto e : a[u]) {
if (visited[e.f]){
continue;
}
ll v = e.f;
ll j = ind[v];
if (dist[j].s > d1 + e.s) {
dist[j].s = d1 + e.s;
up(dist, size, j, ind);
parent[v] = u;
}
}
}
stack<ll> st;
forr(i, n) {
ll j = i;
while (j != -1) {
st.push(j);
j = parent[j];
}
while (!st.empty()) {
cout << st.top() << "->";
st.pop();
}
cout << " Path length is " << ans[i];
cout << '\n';
}
}
This implementation is correct and giving correct output.
As it can be seen every time I select the node with lowest key value(distance from source) and then I update the keys on all the adjacent nodes of the selected node. After updating the keys of the adjacent nodes I am calling the 'up' function as to maintain the min heap properties. But priority queue is present in the c++ stl. How can I use them to avoid the functions up and down.
The thing is I need to be able to find the index of the node-key pair in the mean heap whose key needs to be updated. Here in this code I have used a seperate ind array which is updated every time the min heap is updated.
But how to make use of c++ stl
Like you implied, we cannot random-access efficiently with std::priority_queue. For this case I would suggest that you use std::set. It is not actually a heap but a balanced binary search tree. However it works the desired way you wanted. find, insert and erase methods are all O(log n) so you can insert/erase/update a value with desired time since update can be done with erase-then-insert. And accessing minimum is O(1).
You may refer to this reference implementation like the exact way I mentioned. With your adjacency list, the time complexity is O(E log V) where E is number of edges, V is number of vertices.
And please note that
With default comparator, std::set::begin() method returns the min element if non-empty
In this code, it puts the distance as first and index as second. By doing so, the set elements are sorted with distance in ascending order
% I did not look into the implementation of up and down of your code in detail.

Miller–Rabin SPOJ WA

I am trying to implement Miller-Rabin for the first time. My code is giving correct answer for all the testcases, i tried but still on SPOJ it is giving wrong answer.
Problem Statement: I am supposed to print "YES" if entered number is prime otherwise "NO"
Please help:
Problem Link: http://www.spoj.com/problems/PON/
CODE:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define LL long long
LL expo(LL a,LL b,LL c)
{
LL x=1,y=a;
if(b==0)
return 1;
while(b)
{
if(b%2==1)
x=(x*y)%c;
y=(y*y)%c;
b=b/2;
}
return x;
}
int main()
{
LL t,s,x,a,n,prime,temp;
scanf("%lld",&t);
srand(time(NULL));
while(t--)
{
scanf("%lld",&n);
if(n<2)
puts("NO");
else if(n==2)
puts("YES");
else if(n%2==0)
puts("NO");
else
{
s=n-1;
prime=1;
while(s%2==0)
s=s/2;
for(int i=0;i<20;i++)
{
a=rand()%(n-1)+1;
x=expo(a,s,n);
temp=s;
while((temp!=n-1)&&(x!=1)&&(x!=n-1))
{
x=(x*x)%n;
temp*=2;
}
if((x!=n-1)&&(temp%2==0))
{
prime=0;
break;
}
}
if(prime==0)
puts("NO");
else
puts("YES");
}
}
return 0;
}
Keep in mind that puts appends a newline character '\n' to the string that you're giving. You can try with printf instead.
I think your calculation of s and d is incorrect:
function isStrongPseudoprime(n, a)
d := n - 1; s := 0
while d % 2 == 0
d := d / 2; s := s + 1
t := powerMod(a, d, n)
if t == 1 return ProbablyPrime
while s > 0
if t == n - 1 return ProbablyPrime
t := (t * t) % n
s := s - 1
return Composite
I discuss the Miller-Rabin method in an essay at my blog.
You are getting wrong answer because of integer overflow as you are multiplying 2 long number which can't be holded in a single long long type.
Here is a solution in python to overcome the issue
import random
_mrpt_num_trials = 25 # number of bases to test
def is_probable_prime(n):
assert n >= 2
# special case 2
if n == 2:
return True
# ensure n is odd
if n % 2 == 0:
return False
# write n-1 as 2**s * d
# repeatedly try to divide n-1 by 2
s = 0
d = n - 1
while True:
quotient, remainder = divmod(d, 2)
if remainder == 1:
break
s += 1
d = quotient
assert(2 ** s * d == n - 1)
def try_composite(a):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2 ** i * d, n) == n - 1:
return False
return True
for _ in range(_mrpt_num_trials):
a = random.randrange(2, n)
if try_composite(a):
return False
return True
for i in range(int(input())):
a = int(input())
if is_probable_prime(a):
print("YES")
else:
print("NO")

An error with dec to bin

I have been debugging this function but I don't know why is it throwing 99 when I send 4 to the function.
This is a function to covert from decimal to binary.
Actually, I have tried to cout exp, res and the other variables in each step and then multiply them but I don't know. It doesn't make sense.
int DecToBinary(long num) {
if(num == 0) {
return 0;
}
else if(num == 1) {
return 1;
}
int exp = 0;
int res = 0;
for (; num != 0; exp++){
res = res+num%2*pow(10,exp);
num = num/2;
}
return res;
}
Thank you guys.
if(num == 0) {
return 0;
}
else if(num == 0) {
return 1;
}
You know the second branch will never be executed, right?
Furthermore:
pow(10,exp);
this yields a floating-point number. Be prepared for rounding errors. Even better: don't use pow() at all (you don't need floating-point numbers for working with integers). Simply do the division step by step, accumulating the result in a variable.
int dec2bin(int n)
{
int r = 0, tp = 1;
while (n) {
r += (n % 2) * tp;
n >>= 1;
tp *= 10;
}
return r;
}

Implementing the exponential function with basic arithmetic operations

For the purpose of the exercise, I have to implement the exponential function with the most basic arithmetic operations. I came up with this, where x is the base and y the exponent:
function expAetB() {
product=1;
for (i=0; i<y; i++)
{
product=product*x;
}
return product;
};
However, there are more basic operations than product=product*x;. I should somehow be able to insert instead another for loop which multiply and pass the result, but I can't find a way to do it without falling into an infinite loop.
In the same way that exponentiation is repeated multiplication, so multiplication is simply repeated addition.
Simply create another function mulAetB which does that for you, and watch out for things like negative inputs.
You could go even one more level and define adding in terms of increment and decrement, but that may be overkill.
See, for example, the following program which uses the overkill method of addition:
#include <stdio.h>
static unsigned int add (unsigned int a, unsigned int b) {
unsigned int result = a;
while (b-- != 0) result++;
return result;
}
static unsigned int mul (unsigned int a, unsigned int b) {
unsigned int result = 0;
while (b-- != 0) result = add (result, a);
return result;
}
static unsigned int pwr (unsigned int a, unsigned int b) {
unsigned int result = 1;
while (b-- != 0) result = mul (result, a);
return result;
}
int main (void) {
int test[] = {0,5, 1,9, 2,4, 3,5, 7,2, -1}, *ip = test;
while (*ip != -1) {
printf ("%d + %d = %3d\n" , *ip, *(ip+1), add (*ip, *(ip+1)));
printf ("%d x %d = %3d\n" , *ip, *(ip+1), mul (*ip, *(ip+1)));
printf ("%d ^ %d = %3d\n\n", *ip, *(ip+1), pwr (*ip, *(ip+1)));
ip += 2;
}
return 0;
}
The output of this program shows that the calculations are correct:
0 + 5 = 5
0 x 5 = 0
0 ^ 5 = 0
1 + 9 = 10
1 x 9 = 9
1 ^ 9 = 1
2 + 4 = 6
2 x 4 = 8
2 ^ 4 = 16
3 + 5 = 8
3 x 5 = 15
3 ^ 5 = 243
7 + 2 = 9
7 x 2 = 14
7 ^ 2 = 49
If you really must have it in a single function, it's a simple matter of refactoring the function call to be inline:
static unsigned int pwr (unsigned int a, unsigned int b) {
unsigned int xres, xa, result = 1;
// Catch common cases, simplifies rest of function (a>1, b>0)
if (b == 0) return 1;
if (a == 0) return 0;
if (a == 1) return 1;
// Do power as repeated multiplication.
result = a;
while (--b != 0) {
// Do multiplication as repeated addition.
xres = result;
xa = a;
while (--xa != 0)
result = result + xres;
}
return result;
}

How to simplify this loop?

Considering an array a[i], i=0,1,...,g, where g could be any given number, and a[0]=1.
for a[1]=a[0]+1 to 1 do
for a[2]=a[1]+1 to 3 do
for a[3]=a[2]+1 to 5 do
...
for a[g]=a[g-1]+1 to 2g-1 do
#print a[1],a[2],...a[g]#
The problem is that everytime we change the value of g, we need to modify the code, those loops above. This is not a good code.
Recursion is one way to solve this(although I was love to see an iterative solution).
!!! Warning, untested code below !!!
template<typename A, unsigned int Size>
void recurse(A (&arr)[Size],int level, int g)
{
if (level > g)
{
// I am at the bottom level, do stuff here
return;
}
for (arr[level] = arr[level-1]+1; arr[level] < 2 * level -1; arr[level]++)
{
recurse(copy,level+1,g);
}
}
Then call with recurse(arr,1,g);
Imagine you are representing numbers with an array of digits. For example, 682 would be [6,8,2].
If you wanted to count from 0 to 999 you could write:
for (int n[0] = 0; n[0] <= 9; ++n[0])
for (int n[1] = 0; n[1] <= 9; ++n[1])
for (int n[2] = 0; n[2] <= 9; ++n[2])
// Do something with three digit number n here
But when you want to count to 9999 you need an extra for loop.
Instead, you use the procedure for adding 1 to a number: increment the final digit, if it overflows move to the preceding digit and so on. Your loop is complete when the first digit overflows. This handles numbers with any number of digits.
You need an analogous procedure to "add 1" to your loop variables.
Increment the final "digit", that is a[g]. If it overflows (i.e. exceeds 2g-1) then move on to the next most-significant "digit" (a[g-1]) and repeat. A slight complication compared to doing this with numbers is that having gone back through the array as values overflow, you then need to go forward to reset the overflowed digits to their new base values (which depend on the values to the left).
The following C# code implements both methods and prints the arrays to the console.
static void Print(int[] a, int n, ref int count)
{
++count;
Console.Write("{0} ", count);
for (int i = 0; i <= n; ++i)
{
Console.Write("{0} ", a[i]);
}
Console.WriteLine();
}
private static void InitialiseRight(int[] a, int startIndex, int g)
{
for (int i = startIndex; i <= g; ++i)
a[i] = a[i - 1] + 1;
}
static void Main(string[] args)
{
const int g = 5;
// Old method
int count = 0;
int[] a = new int[g + 1];
a[0] = 1;
for (a[1] = a[0] + 1; a[1] <= 2; ++a[1])
for (a[2] = a[1] + 1; a[2] <= 3; ++a[2])
for (a[3] = a[2] + 1; a[3] <= 5; ++a[3])
for (a[4] = a[3] + 1; a[4] <= 7; ++a[4])
for (a[5] = a[4] + 1; a[5] <= 9; ++a[5])
Print(a, g, ref count);
Console.WriteLine();
count = 0;
// New method
// Initialise array
a[0] = 1;
InitialiseRight(a, 1, g);
int index = g;
// Loop until all "digits" have overflowed
while (index != 0)
{
// Do processing here
Print(a, g, ref count);
// "Add one" to array
index = g;
bool carry = true;
while ((index > 0) && carry)
{
carry = false;
++a[index];
if (a[index] > 2 * index - 1)
{
--index;
carry = true;
}
}
// Re-initialise digits that overflowed.
if (index != g)
InitialiseRight(a, index + 1, g);
}
}
I'd say you don't want nested loops in the first place. Instead, you just want to call a suitable function, taking the current nesting level, the maximum nesting level (i.e. g), the start of the loop, and whatever if needs as context for the computation as arguments:
void process(int level, int g, int start, T& context) {
if (level != g) {
for (int a(start + 1), end(2 * level - 1); a < end; ++a) {
process(level + 1, g, a, context);
}
}
else {
computation goes here
}
}