Defining "<" and ">" in Ruby - ruby

I am a freshman in high-school who has some time on his hands, and I decided it would be beneficial to write some programs that demonstrate what commonly used functions do. I have always wondered what exactly goes into the greater than and less than operators, so I have set out to define them by myself. The only roadblock that I have encountered is how one can assert that a value is negative or positive, without using the greater than or less than operators. So far, I have something that looks like this:
a = 34
b = 42
c = a - b
puts "A is Greater than B" while is_positive?(c)
Does anybody have ideas on how I would define is_positive?(c)?

This question should not be tagged ruby but mathematics.
Then you absolutely do need the equality operator.
If you want to restrict yourself to just the + and - operators, you have no other way of deciding whether a or b is greater, than to count up from 0 and see which value you hit first (which of course is tested using the equality operator)

You mean operator <=> that return -1 first argument is less, 0 if equal and 1 if greater than second? Or maybe you mean sign function that return -1 if argument is less than 0, 0 if is 0 or 1 if is greater than 0?

Related

Is the implementation of `Don't care condition ( X ) in k- map is right

I have a little confusion regarding the Don't care condition in the karnaugh map. As we all know karnaugh map is used to achieve the
complete
accurate/precise
optimal
output equation of 16bit or sometime 32 bits binary solution,till that everything was alright but the problem arises when we insert a dont care conditions in it.
My question was that,
As even the dont care conditions were generated from the o's or 1's solution of truth table & in karnaugh map we sometimes conclude or sometimes ignore dont care conditions in our karnaugh map groups. so is it an ambiguity in a karnaugh map that we ignore dont care conditions in the karnaugh map beacuse we dont know what is behind that dont care condition is it 1 or 0. so afterwards that how could we confidently use to say that our solution is complete or accurate while we are ignoring the dont care conditions in it. May be the dont care we are ignoring contains a 1 in sop and 0 at pos so according to it may contain an error.
A "don't care" is just that. Something that we don't care about. It gives us an opportunity for additional optimization, because that value is not restricted. We are able to make it whatever we wish in order to achieve the most optimal solution.
Because we don't care about it, it doesn't matter what the value is. We will use whatever suits us best (lowest cost, fastest, etc... "optimal"). If it's better as a 1 in one implementation and a 0 in another, so be it, it doesn't matter.
Yes there is always another case with the don't care, but we can say it's complete/accurate because we don't care about the other one. We will treat it whichever way makes our implementation better.
Let's take a very simple example to understand what "don't care conditions" exactly mean.
Let F be a two-variable Boolean function defined by a user as follows:
A B F
0 0 1
0 1 0
This function is not defined when the value of A is 1.
This can mean one of two things :-
The user doesn't care about the value that F produces when A = 1.
The user guarantees that A = 1 will never be given as an input to F.
Both of these cases are collectively known as "don't care conditions".
Now, the person implementing this function can use this fact to their advantage by extending the definition of F to include the cases when A = 1.
Using a K-Map,
B' B
A' | 1 | 0 |
A | X | X |
Without these don't care conditions, the algebraic expression of F would be written as A'B', i.e. F = A'B'.
But, if we modify this map as follows,
B' B
A' | 1 | 0 |
A | 1 | 0 |
then F can be expressed as F = B'.
By modifying this map, we have basically extended the definition of F as follows:
A B F
0 0 1
0 1 0
1 0 1
1 1 0
This method works because the person implementing the function already knows that either the user will not care what happens when A = 1, or the user will never use A = 1 as an input to F.
Another example is a four-variable Boolean function in which each of those 4 variables denotes one distinct bit of a BCD value, and the function gives the output as 1 if the equivalent decimal number is even & 0 if it is odd. Here, since it is guaranteed that the input will never be one of 1010, 1011, 1100, 1101, 1110 & 1111, therefore the person implementing the function can extend the definition of the function to their advantage by including these cases as well.

Efficient way to write ordering instances?

I'm working on a basic Haskell exercise that is set up as follows: a data definition is made, where Zero is declared to be a NaturalNumber, and a series of numbers (printed out by name, so, for instance, four) up to ten is constructed with this.
I didn't have too much trouble with understanding how the declaration of Eq instances works (apart from not having been given an exact explanation for the syntax), but I'm having trouble with declaring all instances I need for Ord -- I need to be able to construct an ordering over the entire set of numbers, such that I'll get True if I input "ten > nine" or something.
Right now, I have this snippet of code. The first two lines should be correct, as I copied them (as I was supposed to) from the exercise itself.
instance Ord NaturalNumber where
compare Zero Zero = EQ
compare Zero (S Zero) = LT
compare (S Zero) Zero = GT
compare x (S x) = LT
The first four lines work fine, but they can't deal with cases like "compare four five", and anything similar to what I typed in the last doesn't work even if I type in something like compare four four = EQ: I get a "conflicting definitions" error, presumably because the x appears twice. If I write something like compare two one = GT instead, I get a "pattern match(es) are overlapped" warning, but it works. However, I also get the result GT when I input compare one two into the actual Haskell platform, so clearly something isn't working. This happens even if I add compare one two = LT below that line.
So clearly I can't finish off this description of Ord instances by writing every instance I could possibly need, and even if I could, it would be incredibly inefficient to write out all 100 instances by hand.
Might anyone be able to provide me with a hint as to how I can resolve this problem and finish off the construction of an ordering mechanism?
What this task focuses on is finding base cases and recursion rules. The first two lines you were given were
instance Ord NaturalNumber where
compare Zero Zero = EQ
This is the first base case, in words:
zero is equal to zero
The other two base cases are:
zero is less than the successor of any NaturalNumber
the successor of any NaturalNumber is greater than zero
Note that your lines three and four only say that 0 < 1 and 1 > 0, but nothing about any other nonzero numbers.
The recursion rule, then, is that it makes no difference if you compare two nonzero numbers, or the numbers they are successors of:
comparing 1 + x and 1 + y is the same as comparing x and y.
Codifying that into Haskell should give you the solution to this exercise.
You'll need to organize your instances in a way that will cover all possible patterns. To make it simpler, remember how your numbers are defined:
one = S Zero
two = S one -- or S (S Zero)
and think in terms of S and Zero, not one, two etc. (they are merely aliases). Once you do this, it should become clear that you're missing a case like:
compare (S x) (S y) = compare x y
Edit:
Like Jakob Runge noticed, also the following base clauses should be improved:
compare Zero (S Zero) = LT
compare (S Zero) Zero = GT
As they're written, they allow comparison only between zero and one. You should change them to cover comparison between zero and any positive number:
compare Zero (S _) = LT
compare (S _) Zero = GT
Your compare function needs to be recursive. You will want your last case to capture the situation where both arguments are the successor of something, and then recurse on what they are the successor of. Additionally, your middle two cases, are probably not what you want, as they will only capture the following cases:
1 > 0
0 < 1
You would like this to be more general, so that you can handle cases like:
S x > 0, for all x
0 < S x, for all x

Scope of variables and the digits function

My question is twofold:
1) As far as I understand, constructs like for loops introduce scope blocks, however I'm having some trouble with a variable that is define outside of said construct. The following code depicts an attempt to extract digits from a number and place them in an array.
n = 654068
l = length(n)
a = Int64[]
for i in 1:(l-1)
temp = n/10^(l-i)
if temp < 1 # ith digit is 0
a = push!(a,0)
else # ith digit is != 0
push!(a,floor(temp))
# update n
n = n - a[i]*10^(l-i)
end
end
# last digit
push!(a,n)
The code executes fine, but when I look at the a array I get this result
julia> a
0-element Array{Int64,1}
I thought that anything that goes on inside the for loop is invisible to the outside, unless I'm operating on variables defined outside the for loop. Moreover, I thought that by using the ! syntax I would operate directly on a, this does not seem to be the case. Would be grateful if anyone can explain to me how this works :)
2) Second question is about syntex used when explaining functions. There is apparently a function called digits that extracts digits from a number and puts them in an array, using the help function I get
julia> help(digits)
Base.digits(n[, base][, pad])
Returns an array of the digits of "n" in the given base,
optionally padded with zeros to a specified size. More significant
digits are at higher indexes, such that "n ==
sum([digits[k]*base^(k-1) for k=1:length(digits)])".
Can anyone explain to me how to interpret the information given about functions in Julia. How am I to interpret digits(n[, base][, pad])? How does one correctly call the digits function? I can't be like this: digits(40125[, 10])?
I'm unable to reproduce you result, running your code gives me
julia> a
1-element Array{Int64,1}:
654068
There's a few mistakes and inefficiencies in the code:
length(n) doesn't give the number of digits in n, but always returns 1 (currently, numbers are iterable, and return a sequence that only contain one number; itself). So the for loop is never run.
/ between integers does floating point division. For extracting digits, you´re better off with div(x,y), which does integer division.
There's no reason to write a = push!(a,x), since push! modifies a in place. So it will be equivalent to writing push!(a,x); a = a.
There's no reason to digits that are zero specially, they are handled just fine by the general case.
Your description of scoping in Julia seems to be correct, I think that it is the above which is giving you trouble.
You could use something like
n = 654068
a = Int64[]
while n != 0
push!(a, n % 10)
n = div(n, 10)
end
reverse!(a)
This loop extracts the digits in opposite order to avoid having to figure out the number of digits in advance, and uses the modulus operator % to extract the least significant digit. It then uses reverse! to get them in the order you wanted, which should be pretty efficient.
About the documentation for digits, [, base] just means that base is an optional parameter. The description should probably be digits(n[, base[, pad]]), since it's not possible to specify pad unless you specify base. Also note that digits will return the least significant digit first, what we get if we remove the reverse! from the code above.
Is this cheating?:
n = 654068
nstr = string(n)
a = map((x) -> x |> string |> int , collect(nstr))
outputs:
6-element Array{Int64,1}:
6
5
4
0
6
8

Algorithm for 0 and any other x

I need to write an algorithm that takes a positive integer x. If integer x is 0, the algorithm returns 0. If it's any other number, the algorithm returns 1.
Here's the catch. I need to condense the algorithm into one equation. i.e. no conditionals. Basically, I need a single equation that equates to 0 if x is zero and 1 if x > 0.
EDIT: As per my comment below. I realize that I wasn't clear enough. I am entering the formula into a system that I don't have control over, hence they strange restrictions.
However, I learned a couple tricks that could be useful in the future!
In C and C++, you can use this trick:
!!x
In those languages, !x evaluates to 1 if x is zero and 0 otherwise. Therefore, !!x evaluates to 1 if x is nonzero and 0 otherwise.
Hope this helps!
Try return (int)(x > 0)
In every programming language I know, (int)(TRUE) == 1 and (int)(FALSE) == 0
Assuming 32-bit integers:
int negX = -x;
return negX >> 31;
Negating x puts a 1 in the highest bit. Shifting right by 31 places moves that 1 to the lowest bit, and fills with 0s. This does nothing to a 0, but converts all positive integers to 1.
This is basically the sign function, but since you specified a positive integer input, you can drop the part that converts negative numbers to -1.
Since virtually every system I know of uses IEEE-754 representation for floating-point numbers, you could just rely on its behavior (namely, that 0.0 / 0.0 is NaN, and NaN != NaN). Pseudo-C (-Java, ...) follows:
float oneOrNAN = (float)(x) / (float)(x);
return oneOrNAN == oneOrNAN;
Like I said, I wasn't clear enough in my problem description. When I said equation, I meant a purely algebraic equation.
I did find an acceptable solution: Y = X/(X - .001)
If it's zero you get 0/ -.001 which is just 0. Any other number, you get 5/4.999 which is close enough to 1 for my particular situation.
However, this is interesting:
!!x
Thanks for the tip!

Check whether a point is inside a rectangle by bit operator

Days ago, my teacher told me it was possible to check if a given point is inside a given rectangle using only bit operators. Is it true? If so, how can I do that?
This might not answer your question but what you are looking for could be this.
These are the tricks compiled by Sean Eron Anderson and he even put a bounty of $10 for those who can find a single bug. The closest thing I found here is a macro that finds if any integer X has a word which is between M and N
Determine if a word has a byte between m and n
When m < n, this technique tests if a word x contains an unsigned byte value, such that m < value < n. It uses 7 arithmetic/logical operations when n and m are constant.
Note: Bytes that equal n can be reported by likelyhasbetween as false positives, so this should be checked by character if a certain result is needed.
Requirements: x>=0; 0<=m<=127; 0<=n<=128
#define likelyhasbetween(x,m,n) \
((((x)-~0UL/255*(n))&~(x)&((x)&~0UL/255*127)+~0UL/255*(127-(m)))&~0UL/255*128)
This technique would be suitable for a fast pretest. A variation that takes one more operation (8 total for constant m and n) but provides the exact answer is:
#define hasbetween(x,m,n) \
((~0UL/255*(127+(n))-((x)&~0UL/255*127)&~(x)&((x)&~0UL/255*127)+~0UL/255*(127-(m)))&~0UL/255*128)
It is possible if the number is a finite positive integer.
Suppose we have a rectangle represented by the (a1,b1) and (a2,b2). Given a point (x,y), we only need to evaluate the expression (a1<x) & (x<a2) & (b1<y) & (y<b2). So the problems now is to find the corresponding bit operation for the expression c
Let ci be the i-th bit of the number c (which can be obtained by masking ci and bit shift). We prove that for numbers with at most n bit, c<d is equivalent to r_(n-1), where
r_i = ((ci^di) & ((!ci)&di)) | (!(ci^di) & r_(i-1))
Prove: When the ci and di are different, the left expression might be true (depends on ((!ci)&di)), otherwise the right expression might be true (depends on r_(i-1) which is the comparison of next bit).
The expression ((!ci)&di) is actually equivalent to the bit comparison ci < di. Hence, this recursive relation return true that it compares the bit by bit from left to right until we can decide c is smaller than d.
Hence there is an purely bit operation expression corresponding to the comparison operator, and so it is possible to find a point inside a rectangle with pure bitwise operation.
Edit: There is actually no need for condition statement, just expands the r_(n+1), then done.
x,y is in the rectangle {x0<x<x1 and y0<y<y1} if {x0<x and x<x1 and y0<y and y<y1}
If we can simulate < with bit operators, then we're good to go.
What does it mean to say something is < in binary? Consider
a: 0 0 0 0 1 1 0 1
b: 0 0 0 0 1 0 1 1
In the above, a>b, because it contains the first 1 whose counterpart in b is 0. We are those seeking the leftmost bit such that myBit!=otherBit. (== or equiv is a bitwise operator which can be represented with and/or/not)
However we need some way through to propagate information in one bit to many bits. So we ask ourselves this: can we "code" a function using only "bit" operators, which is equivalent to if(q,k,a,b) = if q[k] then a else b. The answer is yes:
We create a bit-word consisting of replicating q[k] onto every bit. There are two ways I can think of to do this:
1) Left-shift by k, then right-shift by wordsize (efficient, but only works if you have shift operators which duplicate the last bit)
2) Inefficient but theoretically correct way:
We left-shift q by k bits
We take this result and and it with 10000...0
We right-shift this by 1 bit, and or it with the non-right-shifted version. This copies the bit in the first place to the second place. We repeat this process until the entire word is the same as the first bit (e.g. 64 times)
Calling this result mask, our function is (mask and a) or (!mask and b): the result will be a if the kth bit of q is true, other the result will be b
Taking the bit-vector c=a!=b and a==1111..1 and b==0000..0, we use our if function to successively test whether the first bit is 1, then the second bit is 1, etc:
a<b :=
if(c,0,
if(a,0, B_LESSTHAN_A, A_LESSTHAN_B),
if(c,1,
if(a,1, B_LESSTHAN_A, A_LESSTHAN_B),
if(c,2,
if(a,2, B_LESSTHAN_A, A_LESSTHAN_B),
if(c,3,
if(a,3, B_LESSTHAN_A, A_LESSTHAN_B),
if(...
if(c,64,
if(a,64, B_LESSTHAN_A, A_LESSTHAN_B),
A_EQUAL_B)
)
...)
)
)
)
)
This takes wordsize steps. It can however be written in 3 lines by using a recursively-defined function, or a fixed-point combinator if recursion is not allowed.
Then we just turn that into an even larger function: xMin<x and x<xMax and yMin<y and y<yMax

Resources