(sml) Can I get some help implementing a function that counts the number of cases? - sml

Can I get some help implementing a function that counts the number of cases?
First of all, I'm sorry to ask you the same question over and over again.
I've been trying to implement the function for more than a week, but I don't get the hang of it.
This is the code I wrote now.
fun count (x,nil) = 0
| count(x,y::ys) =
if x=y*2 then 2
else if x=y*4 then 4
else if x=y*10 then 10
else if x=y*20 then 20
else if x=y*100 then 100
else count(x,ys);
I know it's a very ignorant code. But I've practiced implementing the functions you've answered, and I don't understand how to apply them at all.
This is the code I want implemented in c.
int count(int n, int arr[]) {
int cnt = 0;
int num1 = arr[0];
int num2 = arr[1];
if ((n % num1) == 0) cnt++;
if ((n % num2) == 0) cnt++;
if (((n - num1) % arr[1])==0) cnt++;
return cnt;
}
int main() {
int n;
int arr[30];
int res = 0;
scanf("%d", &n);
scanf("%d %d", &arr[0], &arr[1]);
res = count(n, arr);
printf("%d", res);
}
I would like to implement the number function if I do the same thing as the c code. Can I get some help?

I don't completely follow what the intent of the code is, but a nice trick that might be helpful:
In C, if you find yourself updating a local variable, then in SML you can often accomplish the same thing by rebinding the variable:
C:
int x = 0;
if (condition1) x++;
if (condition2) x++;
...
return x;
SML:
let
val x = 0
val x = if condition1 then x+1 else x
val x = if condition2 then x+1 else x
...
in
x
end
Using this trick it should be easy to translate your C function. I'll let you do the rest.
Just one thing to note. When you write code in this style in SML, you're not actually updating local variables at all. The above SML code is equivalent to this, where we make a new variable each time. It's just a bit more convenient to write in the other style.
let
val x0 = 0
val x1 = if condition1 then x0+1 else x0
val x2 = if condition2 then x1+1 else x1
...
in
x2
end

Related

The compiler doesnt show errors but I get no output. Whats wrong?

I'm supposed to write a small code that generates a random number between 2 and 100 and then checks if its a perfect number. I don't get any bugs from the compiler but the output doesn't show my cout lines like " x is a perfect number". Can someone help me with finding the reason?
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
bool PerfectCheck(int x) {
int t; // divisor
int sum; // sum of divisors
for (t = 0; t <= x; t++ ) {
if (x%t == 0) {
sum = sum + t;
}
}
if (sum == x)
return true;
else
return false;
}
int main() {
srand(time(NULL));
int x = rand()%(100-2+1)+2;
if (PerfectCheck(x) == true )
cout << x << "is a perfect number.";
else
cout << x << "is not a perfect number.";
return 0;
}
There are three problems in your PerfectCheck function. First, you don't initialize the sum variable, so it can start off with any value whatsoever; you should set it to zero explicitly in the declaration.
Second, your for loop starts with t as zero, and you check x % t. The modulo operator implicitly involves a division, so using a left-hand value of zero has the same issue as trying to divide by zero, which will cause a crash.
Third, when checking for a perfect number, don't use that number itself in the sum; so, stop your loop with t < x instead of t <= x.
Also, as mentioned in the comments, you can simplify the return statement. The code below works, in the tests I have performed:
bool PerfectCheck(int x)
{
int sum = 0; // sum of divisors - MUST BE INITIALIZED (to zero)
for (int t = 1; t < x; t++) { // DO NOT INCLUDE X ITSELF!!
if (x % t == 0) {
sum += t;
}
}
return (sum == x); // This will already give a "true" or "false" bool value.
}
You could actually make the code a tiny bit more 'efficient', by initializing sum to 1 and then starting the loop from t = 2 (all numbers divide by 1, after all).
Feel free to ask for further clarification and/or explanation.
if (x%t == 0) calculates the remainder after dividing x by t and compares the result with 0. That statement is correct, but look at the previous code for (t = 0; t <= x; t++ ) {. The first value of t is 0, so you have a division by zero. More than likely that is crashing your program which is why you see no output. Change for (t = 0; t <= x; t++ ) { to for (t = 1; t <= x; t++ ) {.
Also I believe the definition of a perfect number does not include division by the number itself. So the for loop should actually be for (t = 1; t < x; t++ ) {.
Finally you are using the sum variable to add up the divisors but you do not give it an initial value. Your code should say int sum = 0;.
Three errors in a ten line program (plus various style issues). Imagine how many errors here might be in a 5000 line program. Programming is tricky, you have to be very focused and get your code exactly right, nearly right is not good enough.

unable to understand the usage of ternary operator

Someone posted this as a solution and I am unable to understand it as a whole, but especially the while loop.
The question is that I have an array of n digits, and I have to print the number of times the greatest element of the array appears.
#include <iostream>
int main(){
int c, n, max = 0;
std::cin.ignore();
while(std::cin >> n)
max < n ? c = !!(max = n) : c += max == n;
std::cout << c;
return 0;
}
It looks like someone has tried to make this code as short as possible. That is rarely a good goal for a program. We can unpick the code step by step to get back to something more reasonable.
First the ternary operator max < n ? c = !!(max = n) : c += max == n; can be converted to:
if (max < n) {
c = !!(max = n);
} else {
c += max == n;
}
c = !!(max = n); is a "clever" way of setting c to 1 and max to n at the same time (though it'll fail if n is 0), this can be rewritten as:
max = n;
c = 1;
Lastly c += max == n is a "clever" way of only incrementing c when max == n alternatively:
if (max == n){
c++;
}
In summary the body of the while loop would be:
if (max < n) {
max = n;
c = 1;
} else if (max == n){
c++;
}
In real code, readability leads to future maintainability, if somebody showed me this code at work I'd get them to rewrite it. There is no benefit to making code shorter (obviously unless it contains unnecessary operations and can be simplified) and in some cases can actually hamper compiler optimisations.

How to write a recursive function that jumbles up numbers from 0 to 6 in a random manner?

Basically i want to write a function that takes values from 0 to 6 and gives back a random assortment such as 2,3,4,5,0,1,6. Here is the code that i came up with. However the problem is that the integer prev (meaning previous) does not store all the old values of r (random number) and thus some values end up being repeated. How might i fix this?
int s(int b)
{
// b is 7
int h = b-1;
int prev = -1;// to store the previous r value
srand(time(0));
for (int i = 0; i < b; i++)
{
int r = rand()%(h - 0 + 1) + 0;
if (r != prev)
{
cout << r << endl;
prev = r;
}
else if (r == prev)
{
s(b);
}
}
return 0;
}
From the comments, this sounds more like a homework problem than a practical problem because you said "No arrays allowed". But I suppose it is an interesting problem.
Here's some code, in Java with only loops, if statements, and with no arrays, as required.
It outputs a random permutation of the set 0, 1, ..., N, shuffled with the Fisher-Yates algorithm.
void printRandom(int N) {
long used = 0;
for (int i = 0; i < N; i++) {
int randomIndex = ThreadLocalRandom.current().nextInt(N - Long.bitCount(used));
for (int j = 0; j < N; j++) {
if ((used & (1L << j)) == 0) {
if (randomIndex-- == 0) {
System.out.print(j + " ");
used = used | (1L << j);
break;
}
}
}
}
}
It is unfortunately limited to the size of a long on your system :)
I think the best way to solve this problem is by using an aux funtion that stores in a variable all the numbers printed until the moment, check if the new number is in the used numbers variable, if not add it to the variable (you can use strings? I know that they are arrays of char's but maybe you can)
Something like this:
function aux(int b, char *variables_printed, int iterations_left)
if (b = 0) then print variables_printed
else
int n = generate_random_number() %b
while (n in variables_printed)
n= (n+random_number) % b
variables_printed += n
aux(b, variables_printed, iterations_left-1)
And your other function:
function s(b)
if b < 0 return 0
else
char *variables_to_print
aux(b, variables_to_print, b)
If you can not use strings, you can do it with long as konsolas said.

Rephrase pascal code to c++ so it can work as efficient as possible

So I got this task where I have pascal code and I need to get out whats the result. That wouldn't be a problem because I know pascal, but I need it to run in 1 second or less with numbers up to 10^9.
readln(N);
counter:=0;
for i:=N-1 downto 1 do begin
counter:= counter + 1;
if N mod i = 0 then break;
end;
writeln(counter);
Here is my code
#include <iostream>
using namespace std;
int main()
{
int x;
int counter = 0;
cin>>x;
for (int i = 2; i <= x; i++){
if (x % i == 0){
counter = x - x / i;
break;
}
}
cout<<counter;
return 0;
}
but it still cant quite get max score.
Restate problem:
1) Compute F = largest proper factor of X
2) Output X-F
Instead of directly searching for the largest proper factor, apply three trivial optimizations (maybe something more advanced will be needed, but first see if three trivial optimizations are enough).
A) Find S = smallest factor of X greater than 1. Output X-(X/S)
B) Special case for prime
C) Special case for even
int largest_proper_factor(int X)
{
if ( X % 2 == 0 ) return X/2; // Optimize even
// Note the add of .5 is only needed for non compliant sqrt version that
// might return a tiny fraction less than the exact answer.
int last = (int)(.5 + std::sqrt( (double) X )) );
for ( int i=3; i<=last; i+=2 ) // big savings here because even was optimized earlier
{
if ( X % i == 0 ) return X/i;
}
return 1; // special case for prime
}
Numbers like 10^9 usually indicate contest problems, which need creative thinking instead of fast CPU...
See, N mod i = 0 means N is divisible by i. So the loop counts numbers between N and one of its divisor (possibly plus one... Check it.) Which one — remains for you.
Ok i got the result i wanned:
#include <iostream>
using namespace std;
int main()
{
int x;
int counter = 0;
cin>>x;
for (int i = 2; i <= x; i++){
if (x % i == 0){
counter = x - x / i;
break;
}
if (x / 4 == i){
i = x - 1;
}
}
cout<<counter;
return 0;
}
Thank you everyone who helped me:)

What's wrong with this Pollard Rho implementation

#include <iostream>
#include <cstdlib>
typedef unsigned long long int ULL;
ULL gcd(ULL a, ULL b)
{
for(; b >0 ;)
{
ULL rem = a % b;
a = b;
b = rem;
}
return a;
}
void pollard_rho(ULL n)
{
ULL i = 0,y,k,d;
ULL *x = new ULL[2*n];
x[0] = rand() % n;
y = x[0];
k = 2;
while(1){
i = i+1;
std::cout << x[i-1];
x[i] = (x[i-1]*x[i-1]-1)%n;
d = gcd(abs(y - x[i]),n);
if(d!= 1 && d!=n)
std::cout <<d<<std::endl;
if(i+1==k){
y = x[i];
k = 2*k;
}
}
}
int main()
{
srand(time(NULL));
pollard_rho(10);
}
This implementation is derived from CLRS 2nd edition (Page number 894). while(1) looks suspicious to me. What should be the termination condition for the while loop?
I tried k<=n but that doesn't seem to work. I get segmentation fault. What is the flaw in the code and how to correct it?
I only have a 1st edition of CLRS, but assuming it's not too different from the 2nd ed., the answer to the termination condition is on the next page:
This procedure for finding a factor may seem somewhat mysterious at first. Note, however, that POLLARD-RHO never prints an incorrect answer; any number it prints is a nontrivial divisor of n. POLLARD-RHO may not print anything at all, though; there is no guarantee that it will produce any results. We shall see, however, that there is good reason to expect POLLARD-RHO to print a factor of p of n after approximately sqrt(p) iterations of the while loop. Thus, if n is composite, we can expect this procedure to discover enough divisors to factor n completely after approximately n1/4 update, since every prime factor p of n except possibly the largest one is less than sqrt(n).
So, technically speaking, the presentation in CLRS doesn't have a termination condition (that's probably why they call it a "heuristic" and "procedure" rather than an "algorithm") and there are no guarantees that it will ever actually produce anything useful. In practice, you'd likely want to put some iteration bound based on the expected n1/4 updates.
Why store all those intermediary values? You really don't need to put x and y in a array. Just use 2 variables which you keep reusing, x and y.
Also, replace while(1) with while(d == 1) and cut the loop before
if(d!= 1 && d!=n)
std::cout <<d<<std::endl;
if(i+1==k){
y = x[i];
k = 2*k;
So your loop should become
while(d == 1)
{
x = (x*x - 1) % n;
y = (y*y - 1) % n;
y = (y*y - 1) % n;
d = abs(gcd(y-x,n))%n;
}
if(d!=n)
std::cout <<d<<std::endl;
else
std::cout<<"Can't find result with this function \n";
Extra points if you pass the function used inside the loop as a parameter to pollard, so that if it can't find the result with one function, it tries another.
Try replacing while(1) { i = i + 1; with this:
for (i = 1; i < 2*n; ++i) {