Visual basic clamping a number - visual-studio-2013

In Visual Basic, I need a way to clamp a number, preventing it from becoming too small or large. It has to fit one line, so should ideally look something like this clamp(x,min,max). I've tried finding a way to do this but could not find anything, any ideas on how to do this?

try this: (true if a change has been made, and false otherwise)
Function clamp(ByRef myNum as Integer, min as Integer, max as Integer) as Boolean
If myNum < min Then
myNum = min
Return True
End If
If myNum > max Then
myNum = max
Return True
End If
Return False
End Function

Related

Lua Compare two Tables values No Order

I wonder if there is a faster way to check if two tables are equal (without order in the keys).
This is my solution
function TableCompareNoOrder(table1,table2)
if #table1 ~= #table2 then return false end
local equal = false
for key, item in pairs(table1) do
for key2, item2 in pairs(table2) do
if item == item2 then equal = true end
end
if equal == false then return false end
end
local equal = false
for key, item in pairs(table2) do
for key2, item2 in pairs(table1) do
if item == item2 then equal = true end
end
if equal == false then return false end
end
return equal
end
a = {1,2,3,0}
b = {2,3,1,0}
print(TableCompareNoOrder(a,b))
Yes, there are faster ways. Your approach is currently O(n²) as it has to compare each element with each other element. One way is to sort the arrays first. Another one would be to build a lookup table ("set") using the hash part. If hash access is assumed to take amortized constant time, this should run in O(n) time - significantly faster. It will take O(n) additional memory but leaves the passed tables intact; to do the same using sorting you'd have to first create a copy, then sort it.
The hash approach looks like the following (and also works for values like tables which are compared by reference and can't be sorted unless a metatable is set or a custom comparator function is supplied):
function TableCompareNoOrder(table1, table2)
if #table1 ~= #table2 then return false end
-- Consider an early "return true" if table1 == table2 here
local t1_counts = {}
-- Check if the same elements occur the same number of times
for _, v1 in ipairs(table1) do
t1_counts[v1] = (t1_counts[v1] or 0) + 1
end
for _, v2 in ipairs(table2) do
local count = t1_counts[v2] or 0
if count == 0 then return false end
t1_counts[v2] = count - 1
end
return true
end
For the sake of completeness, here's a simple implementation using sorting:
function TableCompareNoOrder(table1, table2)
if #table1 ~= #table2 then return false end
-- Lazy implementation: Sort copies of both tables instead of using a binary search. Takes twice as much memory.
local t1_sorted = {table.unpack(table1)} -- simple way to copy the table, limited by stack size
table.sort(t1_sorted)
local t2_sorted = {table.unpack(table2)}
table.sort(t2_sorted)
for i, v1 in ipairs(t1_sorted) do
if t2_sorted[i] ~= v1 then return false end
end
return true
end
This should roughly run in O(n log n) (performance is determined by the sorting algorithm, usually quicksort which has this as it's average running time).

Elegant way to pass as an optional parameter to make the subroutine work as if it was omitted?

In VB6, the function Mid(string, start, [length]) has an optional parameter length. If omitted, the whole characters after the start bound will be passed.
Say I want this default behaviour only in a certain condition:
s = Mid(s, i, IIf(condition, j, TheValue)) ' What could be TheValue?
Since length is of Variant type, I tried Empty. It didn't work. Neither did -1 and Nothing.
I didn't want to duplicate to Mid call in an If-Then-Else clause or somehow else. Is this possible?
Here is a working sample with OP's s = Mid(s, i, IIf(condition, j, TheValue)) line
Option Explicit
Property Get TheValue(Optional RetVal As Variant)
TheValue = RetVal
End Property
Private Sub Form_Load()
Dim s As String
Dim i As Long
Dim j As Long
Dim condition As Boolean
s = "test test test"
i = 6: j = 3
condition = False
s = Mid(s, i, IIf(condition, j, TheValue)) '<--- this works!
Debug.Print s
End Sub
Notice how TheValue returns a "missing" Variant i.e. one which tests positive for IsMissing and can be used in place of optional parameters instead of not passing actual argument.
No such value exists. When you omit the length parameter, the compiler chooses a different path through the VBRT -- it produces different code. If you want to emulate that, you need to do the same thing, using an If-Else or similar construct to handle the two cases, like #ÉtienneLaneville suggests
As an alternative to #Étienne's solution, VB provides the IsMissing method:
Public Function Mid(p_sString As String, p_iStart As Integer, Optional p_iLength As Integer) As String
If IsMissing(p_iLength) Then
Mid = VBA.Mid(p_sString, p_iStart)
Else
Mid = VBA.Mid(p_sString, p_iStart, p_iLength)
End If
End Function
And as this wrapper method returns a string, I suggest using the String verions of Mid, which is Mid$. The later is slightly faster than the Variant version (Mid)
This was nicely explained at this site, but at the time of this posting, the request times out. Not sure if gone forever or just a temporary problem.
You could define your own Mid function:
Public Function Mid(p_sString As String, p_iStart As Integer, Optional p_iLength As Integer = -1) As String
If p_iLength < 0 Then
Mid = VBA.Mid(p_sString, p_iStart)
Else
Mid = VBA.Mid(p_sString, p_iStart, p_iLength)
End If
End Function
This should work with the code from your question, using -1 (or any negative integer) as TheValue.
In c++, std::string these optional arguments are represented by either 0 when the default effect is zero position or length or std::string::npos when it is "infinite" length. You can explicitly supply that value and get the same behaviour.
I don't know what the equivalent constant is in m/s strings [In fact it is a different function definition, so there isn't one]. The alternative would be to pass in the string length, as that is the longest length currently possible.
The ?: ternary operator is an easy way to present 2 values with a condition to choose between them.

Visual Basic - Input Validation

I need help with a little problem. I haven't been programming long and can't figure out how to fix this. I have a small project for school and I can't figure out why I'm getting this error when validating inputs.
For example, I'm checking if the input is valid and between a min and max range by creating a function to return a true or false value based on the values entered. The reason I'm using a function is because I'm doing multiple similar checks and I figured rather than rewriting it out again, this was the best way to do this task.
Do While inputValid(string, min, max)
This is my validation, below is the simple function to validate this.
Private Function inputValid(input As String, min As Integer, max As Integer)
If Not IsNumeric(input) Then
Return False
End If
If input > min Or input < max Then
Return False
Else
Return True
End If
End Function
For some reason, despite the fact it should make sure that the value is numeric before it checks whether it's within a numerical range. It still sends me an error when I type nothing or a string in because it's trying to convert it to a double yet if I'm not doing any between range checks, it checks just fine if it's only numeric with no errors.
Can anyone help me fix this? Thanks!
You could use CInt to convert the string to Integer
Private Function inputValid(input As String, min As Integer, max As Integer)
Dim v as Integer
If Not IsNumeric(input) Then
Return False
End If
v=CInt(input)
If v < min Or v > max Then
Return False
Else
Return True
End If
End Function
You might be better off served using a regular expression to do the numeric validation on the string
Private Function inputValid(input As String, min As Integer, max As Integer)
dim regex as new Regex("[\d]+")
If not regex.isMatch(input) OrElse cint(input) > min OrElse cint(input) < max Then
Return False
Else
Return True
End If
End Function
You can use the Integer.TryParse function to check if a string can be converted to an integer.
Also, you can return a boolean which is the result of a comparison: instead of something like If x > 4 Then Return True you can use Return x > 4.
So your function could look like
Private Function StringIsValidInteger(s As String, min As Integer, max As Integer) As Boolean
Dim tmp As Integer
If Integer.TryParse(s, tmp) Then
Return (tmp >= min AndAlso tmp <= max)
End If
Return False
End Function
Sorry, guys. I was returning true and false the wrong way around it appears because I needed to continue the loop it needed to be true where it would usually be false in regular validation.
By simply changing around in the inputValid function the true and false return types, it works fine.
Thanks for your help guys.

I am attempting to create a method which generates a true or false return value for a Fibonacci detection method in Ruby

I am attempting to create a method which generates a true or false return value when a number is given as its argument to detect if the number is a Fibonacci sequence, although I have never encountered a number like so:
2.073668380220713e+21 .
Forgive my ignorance but is there a way to deal with this type of value in ruby to make it work in the method below?
def is_fibonacci?(num)
high_square = Math.sqrt((5 * num) * num + 4)
low_square = Math.sqrt((5 * num) * num - 4)
# If high_square or low_square are perfect squares, return true, else false.
high_square == high_square.round || low_square == low_square.round ? true : false
end
puts is_fibonacci?(927372692193078999171) # Trying to return false, but returns true. The sqrt of this number is 2.073668380220713e+21.
puts is_fibonacci?(987) # Returns true as expected.
I believe because it's such a large number it's being displayed as scientific notation by Ruby and not able to work in your is_fibonacci? method with the basic Math library.
You might want to look into using the BigMath library for Ruby http://ruby-doc.org/stdlib-1.9.3/libdoc/bigdecimal/rdoc/BigMath.html
Edit As Niel pointed out, it's a Ruby float and has therefore lost precision. Big Math should still do the trick for you.

Fastest way to get maximum value from an exclusive Range in ruby

Ok, so say you have a really big Range in ruby. I want to find a way to get the max value in the Range.
The Range is exclusive (defined with three dots) meaning that it does not include the end object in it's results. It could be made up of Integer, String, Time, or really any object that responds to #<=> and #succ. (which are the only requirements for the start/end object in Range)
Here's an example of an exclusive range:
past = Time.local(2010, 1, 1, 0, 0, 0)
now = Time.now
range = past...now
range.include?(now) # => false
Now I know I could just do something like this to get the max value:
range.max # => returns 1 second before "now" using Enumerable#max
But this will take a non-trivial amount of time to execute. I also know that I could subtract 1 second from whatever the end object is is. However, the object may be something other than Time, and it may not even support #-. I would prefer to find an efficient general solution, but I am willing to combine special case code with a fallback to a general solution (more on that later).
As mentioned above using Range#last won't work either, because it's an exclusive range and does not include the last value in it's results.
The fastest approach I could think of was this:
max = nil
range.each { |value| max = value }
# max now contains nil if the range is empty, or the max value
This is similar to what Enumerable#max does (which Range inherits), except that it exploits the fact that each value is going to be greater than the previous, so we can skip using #<=> to compare the each value with the previous (the way Range#max does) saving a tiny bit of time.
The other approach I was thinking about was to have special case code for common ruby types like Integer, String, Time, Date, DateTime, and then use the above code as a fallback. It'd be a bit ugly, but probably much more efficient when those object types are encountered because I could use subtraction from Range#last to get the max value without any iterating.
Can anyone think of a more efficient/faster approach than this?
The simplest solution that I can think of, which will work for inclusive as well as exclusive ranges:
range.max
Some other possible solutions:
range.entries.last
range.entries[-1]
These solutions are all O(n), and will be very slow for large ranges. The problem in principle is that range values in Ruby are enumerated using the succ method iteratively on all values, starting at the beginning. The elements do not have to implement a method to return the previous value (i.e. pred).
The fastest method would be to find the predecessor of the last item (an O(1) solution):
range.exclude_end? ? range.last.pred : range.last
This works only for ranges that have elements which implement pred. Later versions of Ruby implement pred for integers. You have to add the method yourself if it does not exist (essentially equivalent to special case code you suggested, but slightly simpler to implement).
Some quick benchmarking shows that this last method is the fastest by many orders of magnitude for large ranges (in this case range = 1...1000000), because it is O(1):
user system total real
r.entries.last 11.760000 0.880000 12.640000 ( 12.963178)
r.entries[-1] 11.650000 0.800000 12.450000 ( 12.627440)
last = nil; r.each { |v| last = v } 20.750000 0.020000 20.770000 ( 20.910416)
r.max 17.590000 0.010000 17.600000 ( 17.633006)
r.exclude_end? ? r.last.pred : r.last 0.000000 0.000000 0.000000 ( 0.000062)
Benchmark code is here.
In the comments it is suggested to use range.last - (range.exclude_end? ? 1 : 0). It does work for dates without additional methods, but will never work for non-numeric ranges. String#- does not exist and makes no sense with integer arguments. String#pred, however, can be implented.
I'm not sure about the speed (and initial tests don't seem incredibly fast), but the following might do what you need:
past = Time.local(2010, 1, 1, 0, 0, 0)
now = Time.now
range = past...now
range.to_a[-1]
Very basic testing (counting in my head) showed that it took about 4 seconds while the method you provided took about 5-6. Hope this helps.
Edit 1: Removed second solution as it was totally wrong.
I can't think there's any way to achieve this that doesn't involve enumerating the range, at least unless as already mentioned, you have other information about how the range will be constructed and therefore can infer the desired value without enumeration. Of all the suggestions, I'd go with #max, since it seems to be most expressive.
require 'benchmark'
N = 20
Benchmark.bm(30) do |r|
past, now = Time.local(2010, 2, 1, 0, 0, 0), Time.now
#range = past...now
r.report("range.max") do
N.times { last_in_range = #range.max }
end
r.report("explicit enumeration") do
N.times { #range.each { |value| last_in_range = value } }
end
r.report("range.entries.last") do
N.times { last_in_range = #range.entries.last }
end
r.report("range.to_a[-1]") do
N.times { last_in_range = #range.to_a[-1] }
end
end
user system total real
range.max 49.406000 1.515000 50.921000 ( 50.985000)
explicit enumeration 52.250000 1.719000 53.969000 ( 54.156000)
range.entries.last 53.422000 4.844000 58.266000 ( 58.390000)
range.to_a[-1] 49.187000 5.234000 54.421000 ( 54.500000)
I notice that the 3rd and 4th option have significantly increased system time. I expect that's related to the explicit creation of an array, which seems like a good reason to avoid them, even if they're not obviously more expensive in elapsed time.

Resources