Shortcut criteria check with adding decimal as binary - excel

good day,
I've made a program that has several prerequisites before proceeding and have written a scoring system to tally if all criteria are met without needing several if statements.
In addition i continue to write if statements if criteria are not met to alert the issue but this too is getting crazy with if a or b or c or d . . . statements is there a quicker mathematical way to summaries this? In some cases i have 6 or 7 prerequisites, isnt there a way i can count remainder or something of decimal to binary?
here is a dummy example of what i mean
dim points as integer
points = 0
if len(range("A1") ) = 6 then points = points + 1 'example checks length
if Cdbl(range("B1") ) >= Cdbl(Date) then points = points + 2 'example checks if date is in future
if not isempty(range("C1")) then points = points + 4 'example checks field is not blank
if points = 7 then
[do some code]
msgbox "criteria met"
else
' this is what I want summarized with 1 nice mathematical equation
if points = 1 or points = 3 or points = 5 or points = 7 then
msgbox "problem is A1"
end if
if points = 2 or points = 3 or points = 6 or points = 7 then
msgbox "problem is B1"
end if
if points = 4 or points = 5 or points = 6 or points = 7 then
msgbox "problem is C1"
end if
end if

Yes. You to just need to use And. points And 1 will return 1 (which will be equivalent to true if used that way) if points is odd.
points And 6 will return 6 if the the number in binary ends in 110 or 111.

Related

How to calculate the time complexity for nested for loops in the following example?

So in the following code, I am trying I am passing a (huge)number-string to the function where I have to find the maximum product of consecutive m digits
So, first, I am looping through let's say n-string and then the inner loop looping through m numbers.
So the inner loop is affected by the if-statement which makes a jump of m indexes if the next number is 0.
EDIT : 1
Actual Problem Question:
The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.
731671765313306249192251....(1000digits)
Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
Example:
m = 12 number = "1234567891120123456704832...(1000 digits)"
So in 1st iteration function will calculate the product of 1st 12 digits(i.e. from index-11 to index-0 - "1234567891120123456704832..."
Now, in 2nd iteration when it checks the value at index-12 which is 0 then index will jump to index-13. This way the loop will skip 11 iterations.
For the 3rd Iteration, the inner loop will execute for 4 iterations until it finds 0 ("0123456704832...".
def LargestProductInSeries_1(number,m):
max = -1
product = 1
index = 0
x = 0
while index < len(number)-(m-1):
for j in range(index+(m-1), index-1, -1):
num = int(number[j])
if(not num):
index = j
break
product = product * int(number[j])
max = product if max < product else max
product = 1
index += 1
return max
So according to me, the Worst Case Time Complexity would be O(n*m)
I think the Best Time would be O(n/m) if only once the inner loop is completely iterated or every mth digit is 0 which will make the outer loop execute but the index will jump to every mth digit.
Is my analysis correct?
What will be the Average Time for this case?
Will it be O(n*(log m)). Can anyone explain how? Or how to find Complexity in such cases?

generate random numbers between 0 and 1 in 10 cells in the row , in which the sum of the random number always equal to 7

How can I generate random numbers 0 or 1 in 10 cells in the row, in which the sum of the random number is always equal to 7?
enter image description here
Here's a way to get seven "1"s and three "0"s in random order using RAND and RANK
In A1:J1: =RAND()
In A2:J2: =IF(RANK(A1,$A$1:$J$1,1)>3,1,0)
Available here is a version that I really think works! https://www.dropbox.com/s/ec431fu0h0fhb5i/RandomNumbers.xlsx?dl=0
And here's the '0 and 1' version (sheet 2 at the above link):
De-dup Rankings Randoms First Cut Sorted
0.47999002 7 0.479992063 1 1
0.68823003 3 0.688233075 1 1
0.07594004 9 0.075938331 1 1
0.02077005 10 0.020766892 1 0
0.69217006 2 0.692170173 1 0
0.73355007 1 0.733549516 1 1
0.51546008 6 0.515462872 1 1
0.62308009 4 0.623078278 0
0.33033001 8 0.330331577 1
0.561260011 5 0.561260557 1
Formulae for columns A-C exactly as before, D is just 7 1's, E is:
=VLOOKUP(ROW(E2)-1,B$1:D$11,3,FALSE)
Assuming that you want a list of positive random numbers that add to 7 you can use this following method.
Enter a 0 in the top-left cell (Blue Cell).
Enter =RAND()*7 into the next 9 cells below the 0 (Orange Cells).
Enter a 7 in the cell below the 9 random values (Blue Cell).
Copy the 9 random values and paste-special-values over top to turn the formulas into values.
Sort just these 9 cells in ascending order
In the cell just to the right of the first random value put a formula that subtracts the cell to the left and one above from the cell to the left (Yellow Cells).
Repeat this formula down to the cell next to the 7 that was typed in.
Sum the values in the second column (Green Cell).
That should give you 10 random values whose sum is exactly 7.
The only issue is that getting the values to be between 0 and 1 will take a bit of trial and error.
It appears that trial and error may not be practical. It's about a one in 2,710 times that this list will contain only numbers between 0 and 1. Not overly practical. Sorry.
To answer the question in the post, enter this in A1:J1 as an array formula (ctrl+shift+enter):
=1-(TRANSPOSE(MOD(SMALL(RANDBETWEEN(0,1e12*(ROW(INDIRECT("1:10"))>0))+(ROW(INDIRECT("1:10"))-1)/10,ROW(INDIRECT("1:10"))),1))>0.65)
To answer the question in the post title, do the following:
In A1:J1 enter:
=RAND()
In K1 enter:
=IF(SUM(A1:J1)<7,(7-SUM(A1:J1))/(COUNT(A1:J1)-7),7/SUM(A1:J1))
In L1 enter:
=IF(SUM($A1:$J1)<7,(A1+$K1)/($K1+1),A1*$K1)
Fill over to U1.
I believe the 10 numbers generated will be identically distributed in [0,1), but obviously not uniformly (I'm fairly certain the distribution does not have a name). The numbers can't be considered independent. A few statistics on the distribution:
Mean: 0.7 (as expected)
The other statistics are estimated from 10,000 simulations:
Variance: 0.0295
Kurtosis: -0.648
Skewness: -0.192
Think of it as drawing a sample of size 7 from the set {1, 2, ..., 10}. The 1s correspond to the numbers chosen for inclusion in the sample. Here is some VBA code which generates such samples:
Function sample(n As Long, k As Long) As Variant
'returns a variant of length n
'consisting of k 1s and n-k 0s
'thought of as a sample of {1,...,n} of size k
Dim v As Variant 'vector to hold sample
Dim numbers As Variant
Dim i As Long, j As Long, temp As Long
ReDim v(1 To n)
ReDim numbers(1 To n)
For i = 1 To n
v(i) = 0
numbers(i) = i
Next i
'do k steps of a Fisher-Yates shuffle on numbers
For i = 1 To Application.WorksheetFunction.Min(k, n - 1)
j = Application.WorksheetFunction.RandBetween(i, n)
If i < j Then 'swap
temp = numbers(i)
numbers(i) = numbers(j)
numbers(j) = temp
End If
Next i
'now use the first k elements of the partially shuffled array:
For i = 1 To k
v(numbers(i)) = 1
Next i
sample = v
End Function
Used like: Range("A1:J1").Value = sample(10,7)
Using a bit of brute force, I think I've got a workable solution to the original version of the question which asked for random numbers between 0 and 1.
Cells A1 to A9:
=rand()
Cell A10:
=7-sum(A1:A9)
Now you have 10 numbers that add up to 7, but the last one is probably not in the range 0 to 1. To deal with that, just recalculate the sheet to generate new random numbers until that last value is within range. It takes about 25 recalculations to have a ~95% chance that one of them will be within range, so it could take a while. A little VBA can do that for you very quickly:
Sub rand7()
While Range("A10").Value > 1 Or Range("A10").Value < 0
ActiveSheet.Calculate
Wend
End Sub

Monte Carlo simulation for tossing a coin to get a certain pattern

Inspired by this article: Statistics of Coin-Toss Patterns, I have conducted a Monte Carlo simulation for determining the expected number of tossing a coin to get a certain pattern by using Excel VBA. The following code is the Monte Carlo simulation for tossing a fair coin to get pattern HTH, where H is head (1) and T is tail (0).
Sub Tossing_Coin()
Dim Toss(1000000) As Double, NToss(1000000) As Double, AVToss(1000000) As Double
t0 = Timer
Sheet2.Cells.Clear
a = 0
For j = 1 To 1000000
p1 = Rnd()
If p1 <= 0.5 Then
Toss(1) = 1
Else
Toss(1) = 0
End If
p2 = Rnd()
If p2 <= 0.5 Then
Toss(2) = 1
Else
Toss(2) = 0
End If
i = 2
Do
p3 = Rnd()
If p3 <= 0.5 Then
Toss(i + 1) = 1
Else
Toss(i + 1) = 0
End If
i = i + 1
Loop Until Toss(i - 2) = 1 And Toss(i - 1) = 0 And Toss(i) = 1
NToss(j) = i
a = a + NToss(j)
AVToss(j) = a / j
b = AVToss(j)
Next j
MsgBox "The expected number of tossing is " & b & "." _
& vbNewLine & "The running time of simulation is " & Round(Timer - t0, 2) & " s."
End Sub
The output of the program is as shown below:
which agrees with the result as shown in the article. Other patterns for tossing a fair coin are also match. Despite the results, I'm still feeling uncertain whether the program I wrote is correct or not. My doubt arises when the coin is unfair, meaning p1, p2, and p3 are not equal to 0.5, since I don't have any information to check its accuracy. I also want to know how to write an efficient program in VBA Excel or R to perform simulation above for a longer pattern like THTHTHTHT, THTTHHTHTTH, etc. and its looping is more than 1,000,000 (maybe 100,000,000 or 1,000,000,000) but still pretty fast? Any idea?
To make it more efficient, you could use the bits of a variable by assigning a bit with a toss. Then for each toss, rotate the bits on the left and add the toss result at the first position until the bits on the right are a match with the pattern :
pattern "HTH" : 101
mask for "XXX" : 111
1 toss "H" : 1 And 111 = 001
2 toss "T" : 10 And 111 = 010
3 toss "T" : 100 And 111 = 100
4 toss "H" : 1001 And 111 = 001
5 toss "H" : 10011 And 111 = 011
6 toss "T" : 100110 And 111 = 110
7 toss "H" : 1001101 And 111 = 101 : "HTH" matches the first 3 bits
Note that VBA doesn't have a bit shift operator, but shifting 1 bit on the left is the same as multiplying by 2 :
decimal 9 = 1001 in bits
9 + 9 = 18 = 10010 in bits
18 + 18 = 36 = 100100 in bits
Here is an example to get the average number of toss to match a sequence:
Sub UsageExample()
Const sequence = "HTH"
Const samples = 100000
MsgBox "Average: " & GetTossingAverage(sequence, samples)
End Sub
Function GetTossingAverage(sequence As String, samples As Long) As Double
Dim expected&, tosses&, mask&, tossCount#, i&
Randomize ' Initialize the random generator. '
' convert the [TH] sequence to a sequence of bits. Ex: HTH -> 00000101 '
For i = 1 To Len(sequence)
expected = expected + expected - (Mid$(sequence, i, 1) = "T")
Next
' generate the mask for the rotation of the bits. Ex: HTH -> 01110111 '
mask = (2 ^ (Len(sequence) * 2 + 1)) - (2 ^ Len(sequence)) - 1
' iterate the samples '
For i = 1 To samples
tosses = mask
' generate a new toss until we get the expected sequence '
Do
tossCount = tossCount + 1
' rotate the bits on the left and rand a new bit at position 1 '
tosses = (tosses + tosses - (Rnd < 0.5)) And mask
Loop Until tosses = expected
Next
GetTossingAverage = tossCount / samples
End Function
You'll need one string to store pattern you want to find.
Then after each toss append latest result onto end of results string.
Then check if last n digits of results string == pattern where n = length of pattern.
If match then record numbers of tosses and blank results string and go again ...
You could probably do it in about 20 lines of code! Hope that helps.

fetching data from excel in matlab

I am trying to fetch a column from excel with rows more than 17500. Now problem is that when i call it in MATLAB , it does not gives me whole matrix with all data. it fetches data from somewhere in middle.
Now the real problem is that i have to add up 4 numbers in the column and get average , save it in another column and proceed to next consecutive set of numbers and repeat again till the end..How could i do that in MATLAB .Please help me solve this problem as i am just a rookie. Thank you.
so far i have done is this:
clc
g=xlsread('Data.xlsx',1,'E1:E17500');
x=1;
for i = 1:(17500/4) %as steps has to be stepped at 4 since we need avg of 4
y{i}=((g{x}+g{x+1}+g{x+2}+g{x+3})/4);
x=x+4;
end
xlswrite('Data.xlsx', y, 1, 'F1:F4375');
I see several things here: xlsread with one output gives you a numeric matrix of doubles (not a cell-array). Therefore you should address entries with () and not with {}. The for-loop can be omitted when we use reshape to create a matrix with dimensions 4x4375. The we calculate the average of the 4 values in each column directly with mean (evaluated over the first dimension). To get a column-vector again we have to transpose the result of mean using '.
Here is the code:
g = xlsread('Data.xlsx',1,'E1:E17500');
y = mean(reshape(g,4,[]),1)';
xlswrite('Data.xlsx',y,1,'F1:F4375');
To see in detail what happens within the code, let's see the results of each step using random data for g:
Code:
rng(4);
g = randi(10,12,1)
a = reshape(g,4,[])
b = mean(a,1)
y = b'
Result:
g =
10
6
10
8
7
3
10
1
3
5
8
2
a =
10 7 3
6 3 5
10 10 8
8 1 2
b =
8.5000 5.2500 4.5000
y =
8.5000
5.2500
4.5000

How to convert a table to multiple columns

I have tons of spreadsheets that are formatted like this first table (but with a lot more records and different number of records). I need to make it take all the right information but format it like the second table for importing into Access. Can this be done? Thanks.
..........part 1 part 2 part 3 part 4
Test 1..5
Test 2.............x.........5
Test 3..2.........x..................x
Test 4.......................x.........x
Test 5..x..............................2
Test 1 Part 1 5
Test 2 part 2 x
Test 2 part 3 5
Test 3 part 1 2
Test 3 part 2 x
Test 3 part 4 x
Test 4 part 3 x
Test 4 part 4 x
Test 5 part 1 x
Test 5 part 4 2
Here's one way to do it. You could also use For Each loops for the Ranges.
Dim workingRange1 As Range, workingRange2 As Range
Set workingRange1 = Sheets("Sheet1").UsedRange
Set workingRange2 = Range("PutStuffHere")
For i = 0 to workingRange1.Rows.Count - 2
For j = 0 to workingRange1.Columns.Count - 2
If Not IsEmpty(workingRange1.Cells(i+1, j+1))
workingRange2.Offset(0, 0) = workingRange1.Cells(i+1, 1)
workingRange2.Offset(0, 1) = workingRange1.Cells(1, j+1)
workingRange2.Offset(0, 2) = workingRange1.Cells(i+1, j+1)
End If
Set workingRange2 = workingRange2.Offset(1,0)
Next j
Next i

Resources