How can i make it simple? I have predefined numbers under L0 to L9. When program gets number for example 32 i need to write it under LX as L3 and under LY as L2. Anyone has an idea how to do this ? I need to make it form 0 to 64
if(number == 64){LX=L6;LY=L4;}
if(number == 63){LX=L6;LY=L3;}
if(number == 62){LX=L6;LY=L2;}
You don't give any details on what the type of LX, LY and L0..L9 is, but from what I can see, you want to use each digit of number to look up your corresponding "predefined number" and then put the tens digit in LX and the ones digit in LY.
A straight-forward way is to do the lookup explicitly with a switch
in a function
/* Convert x (in [0..9]) to corresponding "predefined number" */
L_type get_L_num(int x)
{
switch(x) {
case 0: return L0;
...
case 9: return L9;
default: if needed, some error handling...
}
(where L_type is whatever type your predefined number variables are) and use that for each digit as in
{LX = get_L_num(number/10]; LY = get_L_num[number%10]}
Another alternative is to put L0..L9 in an array Lnumbers and then index that as
{LX = Lnumbers[number/10]; LY = Lnumbers[number%10]}
and, if you need to, add range checks for number.
Please note that the use of just /10 to find the tens and %10 to find the ones assumes that number is in [0..99], (which it should be since you asked about [0..64])
Related
How can I convert a z3.String to a sequence of ASCII values?
For example, here is some code that I thought would check whether the ASCII values of all the characters in the string add up to 100:
import z3
def add_ascii_values(password):
return sum(ord(character) for character in password)
password = z3.String("password")
solver = z3.Solver()
ascii_sum = add_ascii_values(password)
solver.add(ascii_sum == 100)
print(solver.check())
print(solver.model())
Unfortunately, I get this error:
TypeError: ord() expected string of length 1, but SeqRef found
It's apparent that ord doesn't work with z3.String. Is there something in Z3 that does?
The accepted answer dates back to 2018, and things have changed in the mean time which makes the proposed solution no longer work with z3. In particular:
Strings are now formalized by SMTLib. (See https://smtlib.cs.uiowa.edu/theories-UnicodeStrings.shtml)
Unlike the previous version (where strings were simply sequences of bit vectors), strings are now sequences unicode characters. So, the coding used in the previous answer no longer applies.
Based on this, the following would be how this problem would be coded, assuming a password of length 3:
from z3 import *
s = Solver()
# Ord of character at position i
def OrdAt(inp, i):
return StrToCode(SubString(inp, i, 1))
# Adding ascii values for a string of a given length
def add_ascii_values(password, len):
return Sum([OrdAt(password, i) for i in range(len)])
# We'll have to force a constant length
length = 3
password = String("password")
s.add(Length(password) == length)
ascii_sum = add_ascii_values(password, length)
s.add(ascii_sum == 100)
# Also require characters to be printable so we can view them:
for i in range(length):
v = OrdAt(password, i)
s.add(v >= 0x20)
s.add(v <= 0x7E)
print(s.check())
print(s.model()[password])
Note Due to https://github.com/Z3Prover/z3/issues/5773, to be able to run the above, you need a version of z3 that you downloaded on Jan 12, 2022 or afterwards! As of this date, none of the released versions of z3 contain the functions used in this answer.
When run, the above prints:
sat
" #!"
You can check that it satisfies the given constraint, i.e., the ord of characters add up to 100:
>>> sum(ord(c) for c in " #!")
100
Note that we no longer have to worry about modular arithmetic, since OrdAt returns an actual integer, not a bit-vector.
2022 Update
Below answer, written back in 2018, no longer applies; as strings in SMTLib received a major update and thus the code given is outdated. Keeping it here for archival purposes, and in case you happen to have a really old z3 that you cannot upgrade for some reason. See the other answer for a variant that works with the new unicode strings in SMTLib: https://stackoverflow.com/a/70689580/936310
Old Answer from 2018
You're conflating Python strings and Z3 Strings; and unfortunately the two are quite different types.
In Z3py, a String is simply a sequence of 8-bit values. And what you can do with a Z3 is actually quite limited; for instance you cannot iterate over the characters like you did in your add_ascii_values function. See this page for what the allowed functions are: https://rise4fun.com/z3/tutorialcontent/sequences (This page lists the functions in SMTLib parlance; but the equivalent ones are available from the z3py interface.)
There are a few important restrictions/things that you need to keep in mind when working with Z3 sequences and strings:
You have to be very explicit about the lengths; In particular, you cannot sum over strings of arbitrary symbolic length. There are a few things you can do without specifying the length explicitly, but these are limited. (Like regex matches, substring extraction etc.)
You cannot extract a character out of a string. This is an oversight in my opinion, but SMTLib just has no way of doing so for the time being. Instead, you get a list of length 1. This causes a lot of headaches in programming, but there are workarounds. See below.
Anytime you loop over a string/sequence, you have to go up to a fixed bound. There are ways to program so you can cover "all strings upto length N" for some constant "N", but they do get hairy.
Keeping all this in mind, I'd go about coding your example like the following; restricting password to be precisely 10 characters long:
from z3 import *
s = Solver()
# Work around the fact that z3 has no way of giving us an element at an index. Sigh.
ordHelperCounter = 0
def OrdAt(inp, i):
global ordHelperCounter
v = BitVec("OrdAtHelper_%d_%d" % (i, ordHelperCounter), 8)
ordHelperCounter += 1
s.add(Unit(v) == SubString(inp, i, 1))
return v
# Your original function, but note the addition of len parameter and use of Sum
def add_ascii_values(password, len):
return Sum([OrdAt(password, i) for i in range(len)])
# We'll have to force a constant length
length = 10
password = String("password")
s.add(Length(password) == 10)
ascii_sum = add_ascii_values(password, length)
s.add(ascii_sum == 100)
# Also require characters to be printable so we can view them:
for i in range(length):
v = OrdAt(password, i)
s.add(v >= 0x20)
s.add(v <= 0x7E)
print(s.check())
print(s.model()[password])
The OrdAt function works around the problem of not being able to extract characters. Also note how we use Sum instead of sum, and how all "loops" are of fixed iteration count. I also added constraints to make all the ascii codes printable for convenience.
When you run this, you get:
sat
":X|#`y}###"
Let's check it's indeed good:
>>> len(":X|#`y}###")
10
>>> sum(ord(character) for character in ":X|#`y}###")
868
So, we did get a length 10 string; but how come the ord's don't sum up to 100? Now, you have to remember sequences are composed of 8-bit values, and thus the arithmetic is done modulo 256. So, the sum actually is:
>>> sum(ord(character) for character in ":X|#`y}###") % 256
100
To avoid the overflows, you can either use larger bit-vectors, or more simply use Z3's unbounded Integer type Int. To do so, use the BV2Int function, by simply changing add_ascii_values to:
def add_ascii_values(password, len):
return Sum([BV2Int(OrdAt(password, i)) for i in range(len)])
Now we'd get:
unsat
That's because each of our characters has at least value 0x20 and we wanted 10 characters; so there's no way to make them all sum up to 100. And z3 is precisely telling us that. If you increase your sum goal to something more reasonable, you'd start getting proper values.
Programming with z3py is different than regular programming with Python, and z3 String objects are quite different than those of Python itself. Note that the sequence/string logic isn't even standardized yet by the SMTLib folks, so things can change. (In particular, I'm hoping they'll add functionality for extracting elements at an index!).
Having said all this, going over the https://rise4fun.com/z3/tutorialcontent/sequences would be a good start to get familiar with them, and feel free to ask further questions.
Consider the problem of finding the k element subsets of a set with n elements. Write a recursive function that takes an array of integers representing the set, the number of integers in the set (n), and the required subset size (k) as input, and displays all subsets with k elements on the screen. You may assume that the elements in the array have unique values. For example, if the array (set) contains the elements [ 8 2 6 7 ], n is 4, and k is 2, then the output is 82 86 87 26 27 67.
Can you help me with this, at least tell what way should I follow?
The type of thing you're talking about is a **combination&&.
There's a recursive definition of the calculation tucked in the middle of the Wikipedia page.
$$\binom{n}{k}=\binom{n-1}{k-1}+\binom{n-1}{k}$$
Figuring out what your base cases are might be tricky, but I think everything you need is there.
I would've right something like this:
subset ( numbers, n, k, index)
{
if (index < n) // end for the recursion. passed through all elements
{
if (k == 0) // end for the recursion. no more elements needed
print ' '
else
{
print numbers[index]
subset(numbers, n, k-1, index+1) // uses the number in the current index
subset(numbers, n, k, index+1) // doesn't use the number in the current index
}
}
call subset(numbers, n, k, 0) to start
notice that because order doesn't play a role in sets, its enough to pass over the elements in one direction
In a recent interview, I was asked this question. I gave the solution by running a loop and checking every one of the x bits by right-shifting 1 every time.
Then he asked if I can do this without running a loop. I tried various approaches but could not find a solution. Can here any bit-fiddling expert help me out?
Example - if num = 15 and x = 2 then result should be true because 1st 2 bits are set in 15(01111).
Thanks
I think following (Java implementation) should work:
/** Returns true if the least significant x bits in n are set */
public static boolean areLSBSet(int n, int x) {
// validate x, n
int y = (1<<x) - 1;
return (n & y) == y;
}
The idea is to quickly find out the number that is 2^x - 1 (this number has all the x least significant bits set) and then taking the bitwise-and with given number n which will give the same number only if exactly that many bits in n are set.
My previous qs. was unclear so I am again putting it in clear terms.
I need an efficient algorithm to count the number of arithmetic progressions in a series. The number of elements in a single AP should be >2.
eg. if the series is {1,2,2,3,4,4} then the different solutions are listed below(with index numbers):
0,1,3
0,2,3
0,1,3,4
0,1,3,5
0,2,3,4
0,2,3,5
hence the answer should be 6
I am not able to code it when these numbers become large and size of array increases. I need an efficient algorithm for this.
First of all, you answer is incorrect. Numbers 2,3,4 (indexes also 2,3,4) form an AP.
Second, here is a simple brute force algorithm:
def find (vec,value,start):
for i from start to length(vec):
if vec[i] == value:
return i
return None
for i from 0 to length(vec) - 2:
for j from i to length(vec) - 1:
next = 2 * vec[j] - vec[i] # the next element in the AP
pos = find(vec,next,j+1)
if pos is None:
continue
print "found AP:\n %d\n %d\n %d" % (i,j,pos)
prev = vec[j]
here = next
until (pos = find(vec,next = 2*here-prev,pos+1)) is None:
print ' '+str(pos)
prev = here
here = next
I don't think you can do better than this O(n^4) because the total number of APs to be printed is O(n^4) (consider a vector of zeros).
If, on the other hand, you want to only print maximal APs, i.e., APs which are not contained in any other AP, then the problem becomes much more interesting...
So, I am working on a program in Scilab which solves a binary puzzle. I have come across a problem however. Can anyone explain to me the logic behind solving a binary sequence with gaps (like [1 0 -1 0 -1 1 -1] where -1 means an empty cell. I want all possible solutions of a given sequence. So far I have:
function P = mogelijkeCombos(V)
for i=1:size(V,1)
if(V(i) == -1)
aantalleeg = aantalleeg +1
end
end
for i=1:2^aantalleeg
//creating combos here
end
endfunction
sorry that some words are in dutch
aantalleeg means amountempty by which I mean the amount of empty cells
I hope I gave you guys enough info. I don't need any code written, I'd just like ideas of how I can make every possible rendition as I am completely stuck atm.
BTW this is a school assignment, but the assignment is way bigger than this and it's just a tiny part I need some ideas on
ty in advance
Short answer
You could create the combos by extending your code and create all possible binary words of the length "amountempty" and replacing them bit-for-bit in the empty cells of V.
Step-by-step description
Find all the empty cell positions
Count the number of positions you've found (which equals the number of empty cells)
Create all possible binary numbers with the length of your count
For each binary number you generate, place the bits in the empty cells
print out / store the possible sequence with the filled in bits
Example
Find all the empty cell positions
You could for example check from left-to-right starting at 1 and if a cell is empty add the position to your position list.
V = [1 0 -1 0 -1 1 -1]
^ ^ ^
| | |
1 2 3 4 5 6 7
// result
positions = [3 5 7]
Count the number of positions you've found
//result
amountempty = 3;
Create all possible binary numbers with the length amountempty
You could create all possible numbers or words with the dec2bin function in SciLab. The number of possible words is easy to determine because you know how much separate values can be represented by a word of amountempty bits long.
// Create the binary word of amountEmpty bits long
binaryWord = dec2bin( i, amountEmpty );
The binaryWord generated will be a string, you will have to split it into separate bits and convert it to numbers.
For each binaryWord you generate
Now create a possible solution by starting with the original V and fill in every empty cell at the position from your position list with a bit from binaryWordPerBit
possibleSequence = V;
for j=1:amountEmpty
possibleSequence( positions(j) ) = binaryWordPerBit(j);
end
I wish you "veel succes met je opdracht"