How to write a constraint that depends on a condition in Circom? - if-statement

I have code of the following form in Circom circuit compiler
template DecodeUint(len) {
signal input x;
signal input pos;
signal output value;
signal output nextpos;
component getV = GetV(len);
if (x <= 23) {
value <== x;
pos ==> nextpos;
}
else if(x == 24) {
value <== 255;
pos + 1 ==> nextpos;
}
}
I'm getting this error:
error[T2005]: Typing error found
┌─ "/Users/ilia/compiling/main-circom/main.circom":93:13
│
93 │ else if(x == 24) {
│ ^^^^^^^ There are constraints depending on the value of the condition and it can be unknown during the constraint generation phase
How do I rewrite the conditions in a form that can be generated into a circuit? Is there something like Quin Selector but for if conditions?

I used LessThan and IsEqual from circomlib which return either 1 or 0 depending on if it's true of false, then multiplied the output of those conditions by the return value and finally used CalculateTotal to sum the multiplied conditions together to get the "result" of all the if branches in an arithmetic way.

Related

My reverse caesar shift assignment works on vscode but not when I submit it to gradescope

I have a homework assignment where I have to make a function that is used to reverse the effects of a caesar shift on a string. For example, if the string after the shift is "fghij", and the shift value is 5, the function should yield "abcde." This works when I try it on visualstudiocode. When I submit the assignment, it seems as if my function did nothing. The function is as follows:
string decryptCaesar(string ciphertext, int rshift)
{
string plaintext;
int cipher_length = ciphertext.length();
for(int a = 0; a < cipher_length; a++)
{
char individual = char(ciphertext[a]);
if(isalpha(individual) == true)
{
if(65 <= int(individual) && int(individual) <= 90)
{
individual = char(((int(individual) - 65 + 26 - rshift) % 26) + 65);
}
else
{
individual = char(((int(individual) - 97 + 26 - rshift) % 26) + 97);
}
}
plaintext += individual;
}
return plaintext;
}
For a start, the values returned from the classification macros (like isalpha) are nonzero if the character falls into the tested class, and zero if not. See this answer for some more detail.
However, the true constant has only one value, so you should not compare the two (true may be the value 1 but isaplha() may return 42).
Instead, simply rely on the fact that non-zero integers become "true" when interpreted in a boolean context:
if (isalpha(individual)) {
blahBlahBlah();
}

Problem with Reversing Large Integers On Leetcode?

I was working on this problem from Leetcode where it has this requirement of reversing numbers whilst staying within the +/-2^31 range. I checked out other solutions made for this problem, and from there created my own solution to it. It worked successfully for numbers ranging from 10 to less than 99,999,999. Going more than that(when trying to submit the code to move to the next question) would throw an error saying:
"Line 17: Char 23: runtime error: signed integer overflow: 445600005 * 10 cannot be represented in type 'int' (solution.cpp)"
This was the input given when trying to submit the code: 1534236469
My code
class Solution {
public:
int reverse(int x) {
int flag = 0;
int rev = 0;
if (x >= pow(2, 31)) {
return 0;
} else {
if (x < 0) {
flag = 1;
x = abs(x);
}
while(x > 0) {
rev = rev * 10 + x % 10;
x /= 10;
}
if (flag == 1) {
rev = rev*(-1);
}
return rev;
}
}
};
As you can see from my code, I added an if statement that would basically return 0 if the number was greater than 2^31. Unfortunately, this was wrong.
Can anyone explain how this can be fixed? Thank you in advance.
Problem statement asks to return 0 if reversed number does not belong to integer range :
If reversing x causes the value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then return 0.
In your code you checked if input fits in integer range but their arises a corner case when the integer has 10 digits and last digit is >2 (and for some cases 2).
Lets consider the input 1534236469: 1534236469 < 2^31 - 1
so program executes as expected now lets trace last few steps of program execution : rev = 964632435 and x = 1 problem arises when following statement is executed :
rev = rev * 10 + x % 10;
Now, even though input can be represented as integer rev * 10 i.e. 9646324350 is greater than integer range and correct value that should be returned is zero
Fix ?
1. Lets consider 10 digit case independently
Even though this can be done, it gives rise to unnecessary complications when last digit is 2
2. Make rev a long integer
This works perfectly and is also accepted, but sadly this is not expected when solving this problem as statement explicitly asks to not use 64-bit integers
Assume the environment does not allow you to store 64-bit integers (signed or unsigned).
3. Checking before multyplying by 10 ?
This works as expected. Before multyplying rev by 10 check if it is >= (pow(2,31)/10)
while(x > 0) {
if (rev >= pow(2, 31)/10 )
return 0;
rev = rev * 10 + x % 10;
x /= 10;
}
I hope this solves your doubt !! Comment if you find something wrong as this is my first answer.
Note : The following if statement is unnecessary as input is always a 32-bit integer
Given a signed 32-bit integer x
if (x >= pow(2, 31)) {
return 0;
}
Edit : As most of the comments pointed it out, instead of pow(2,31), use INT_MAX macro as it suffices here.
public static int reverse(int x) {
boolean isNegative = false;
if (x < 0) {
isNegative = true;
x = -x;
}
long reverse = 0;
while (x > 0) {
reverse = reverse * 10 + x % 10;
x=x/10;
}
if (reverse > Integer.MAX_VALUE) {
return 0;
}
return (int) (isNegative ? -reverse : reverse);
}

How can I print the square roots of the first 25 off integers by using a while loop with i=i+1 instead of i=i+2

When I try to solve this problem I write the following code:
int x = 1;
while(x%2 != 0 && x <= 50) { //x%2 != 0 defines odd integers and x<=50 gives the first 25
cout << pow(x,0.5) << endl;
x = x + 1;
}
This code only prints out the value of the square root of 1. So I edit the code like so:
int x = 1;
while(x%2 != 0 && x <= 50) {
cout << pow(x,0.5) << endl;
x = x + 2;
}
Now it prints out all the 25 odd integer square roots.
So the problem with the first code is clearly that the while loop is stopping once the square root cannot be executed (i.e. when the integer is even). It is executing the square root of 1, moving on to the integer 2, not executing the square root, and instead of then moving onto the integer 3 it is stopping. This is why the second code works: because I am adding 2 it is only ever meeting an odd integer, so always works and thus continues until x<=50.
How can I stop it from stopping and why is it doing this? I would have thought that it would register each and every integer that satisfies the condition but it is not doing this.
while executes while the condition is true. On the second iteration x == 2, so the condition x%2 != 0 becomes false, consequently x%2 != 0 && x <= 50 becomes false and while loop terminates.
You already solved How can I stop it from stopping part by incrementing x by 2, so it's unclear what you are asking here.

If statements with multi conditions

I am trying to form an if statement like so:
int myVariable = -1;
if (0 <= myVariable <= 99)
{
// Do something
}
However, if I assigned -1 to myVariable, which is an int, the if-statement still evaluations to true.
What am I doing wrong ?
That is not the correct way to say what you want in C++ syntax. You want:
int myVariable = -1;
if (0 <= myVariable && myVariable <= 99)
{
// Do something
}
What you wrote does the following:
1) Evaluate 0 <= myVariable, which in your example will be false (converted to 0 in C++ in this context)
2) Then this result (0) is compared against <= 99, so C++ reads "0 <= 99", which is true, so the if statement is true.

C++ reading a sequence of integers

gooday programers. I have to design a C++ program that reads a sequence of positive integer values that ends with zero and find the length of the longest increasing subsequence in the given sequence. For example, for the following
sequence of integer numbers:
1 2 3 4 5 2 3 4 1 2 5 6 8 9 1 2 3 0
the program should return 6
i have written my code which seems correct but for some reason is always returning zero, could someone please help me with this problem.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int x = 1; // note x is initialised as one so it can enter the while loop
int y = 0;
int n = 0;
while (x != 0) // users can enter a zero at end of input to say they have entered all their numbers
{
cout << "Enter sequence of numbers(0 to end): ";
cin >> x;
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
n = n + 1;
y = x;
}
else
{
n = 0;
}
}
cout << "longest sequence is: " << n << endl;
return 0;
}
In your program, you have made some assumptions, you need to validate them first.
That the subsequence always starts at 1
That the subsequence always increments by 1
If those are correct assumptions, then here are some tweaks
Move the cout outside of the loop
The canonical way in C++ of testing whether an input operation from a stream has worked, is simply test the stream in operation, i.e. if (cin >> x) {...}
Given the above, you can re-write your while loop to read in x and test that x != 0
If both above conditions hold, enter the loop
Now given the above assumptions, your first check is correct, however in the event the check fails, remember that the new subsequence starts at the current input number (value x), so there is no sense is setting n to 0.
Either way, y must always be current value of x.
If you make the above logic changes to your code, it should work.
In the last loop, your n=0 is execute before x != 0 is check, so it'll always return n = 0. This should work.
if(x == 0) {
break;
} else if (x > y ) {
...
} else {
...
}
You also need to reset your y variable when you come to the end of a sequence.
If you just want a list of increasing numbers, then your "if" condition is only testing that x is equal to one more than y. Change the condition to:
if (x > y) {
and you should have more luck.
You always return 0, because the last number that you read and process is 0 and, of course, never make x == (y + 1) comes true, so the last statement that its always executed before exiting the loop its n=0
Hope helps!
this is wrong logically:
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
Should be
if(x >= (y+1))
{
I think that there are more than one problem, the first and most important that you might have not understood the problem correctly. By the common definition of longest increasing subsequence, the result to that input would not be 6 but rather 8.
The problem is much more complex than the simple loop you are trying to implement and it is usually tackled with Dynamic Programming techniques.
On your particular code, you are trying to count in the if the length of the sequence for which each element is exactly the successor of the last read element. But if the next element is not in the sequence you reset the length to 0 (else { n = 0; }), which is what is giving your result. You should be keeping a max value that never gets reset back to 0, something like adding in the if block: max = std::max( max, n ); (or in pure C: max = (n > max? n : max );. Then the result will be that max value.