vbscript compare last value to new - vbscript

I have a 4 digit field that is constantly renewd and value changes. I need to print the field if the value in the field has changed more then 4 digits.
Example:
field_value=0111
if field_value=0112 (does not print)
if field_value=0116 (prints the value)

As I don't understand your spec - what exactly are your data and how do you measure the difference? - all I can give you is:
Option Explicit
Dim o : o = -1 ' definitely out of range
Dim n
For Each n In Split("0111 0112 0116 9990 9991 9995 9996")
n = CLng(n)
If 4 <= n - o Then
WScript.Echo o, n, "yes"
o = n ' <-- the important part
Else
WScript.Echo o, n, "no"
End If
Next
output:
cscript 25442674.vbs
-1 111 yes
111 112 no
111 116 yes
116 9990 yes
9990 9991 no
9990 9995 yes
9995 9996 no
If you can't specify the first out of range value or need to treat the first differently, you must use a counted loop.

Related

Converting to and from a number system that doesn't have a zero digit

Consider Microsoft Excel's column-numbering system. Columns are "numbered" A, B, C, ... , Y, Z, AA, AB, AC, ... where A is 1.
The column system is similar to the base-10 numbering system that we're familiar with in that when any digit has its maximum value and is incremented, its value is set to the lowest possible digit value and the digit to its left is incremented, or a new digit is added at the minimum value. The difference is that there isn't a digit that represents zero in the letter numbering system. So if the "digit alphabet" contained ABC or 123, we could count like this:
(base 3 with zeros added for comparison)
base 3 no 0 base 3 with 0 base 10 with 0
----------- ------------- --------------
- - 0 0
A 1 1 1
B 2 2 2
C 3 10 3
AA 11 11 4
AB 12 12 5
AC 13 20 6
BA 21 21 7
BB 22 22 8
BC 23 100 9
CA 31 101 10
CB 32 102 11
CC 33 110 12
AAA 111 111 13
Converting from the zeroless system to our base 10 system is fairly simple; it's still a matter of multiplying the power of that space by the value in that space and adding it to the total. So in the case of AAA with the alphabet ABC, it's equivalent to (1*3^2) + (1*3^1) + (1*3^0) = 9 + 3 + 1 = 13.
I'm having trouble converting inversely, though. With a zero-based system, you can use a greedy algorithm moving from largest to smallest digit and grabbing whatever fits. This will not work for a zeroless system, however. For example, converting the base-10 number 10 to the base-3 zeroless system: Though 9 (the third digit slot: 3^2) would fit into 10, this would leave no possible configuration of the final two digits since their minimum values are 1*3^1 = 3 and 1*3^0 = 1 respectively.
Realistically, my digit alphabet will contain A-Z, so I'm looking for a quick, generalized conversion method that can do this without trial and error or counting up from zero.
Edit
The accepted answer by n.m. is primarily a string-manipulation-based solution.
For a purely mathematical solution see kennytm's links:
What is the algorithm to convert an Excel Column Letter into its Number?
How to convert a column number (eg. 127) into an excel column (eg. AA)
Convert to base-3-with-zeroes first (digits 0AB), and from there, convert to base-3-without-zeroes (ABC), using these string substitutions:
A0 => 0C
B0 => AC
C0 => BC
Each substitution either removes a zero, or pushes one to the left. In the end, discard leading zeroes.
It is also possible, as an optimisation, to process longer strings of zeros at once:
A000...000 = 0BBB...BBC
B000...000 = ABBB...BBC
C000...000 = BBBB...BBC
Generalizable to any base.

Why does Rspec of RubyMonk says it true where the outcome is false?

I have this:
def kaprekar?(k)
string_k = (k * k).to_s
length_k = k.to_s.length.to_i
length_k2 = string_k.to_s.length.to_i
number1 = string_k[0...length_k].to_i
number2 = string_k[length_k..length_k2].to_i
number1 + number2 == k
end
and according to this error message for 297 it output is true.
returns true for 297
RSpec::Expectations::ExpectationNotMetError
expected false to be true
But when I do the same on repl.it I see this output:
kaprekar?(297)
string_k : 88209
length_k : 3
length2 : 5
number1 : 882
number2: 9
=> false
which is the right answer.
Can anyone explain why Rubymonk say the outcome is true?
Edit 1:
The task is:
Problem Statement
9 is a Kaprekar number since
9 ^ 2 = 81 and 8 + 1 = 9
297 is also Kaprekar number since
297 ^ 2 = 88209 and 88 + 209 = 297.
In short, for a Kaprekar number k with n-digits, if you square it and add the right n digits >to the left n or n-1 digits, the resultant sum is k.
Find if a given number is a Kaprekar number.
Can anyone explain why Rubymonk say the outcome is true?
RubyMonk is actually saying that the expected outcome is true, whereas your implementation yields false. Your edit even states that 297 is a Kaprekar number. Hopefully my answer will clarify this.
Quoth Kaprekar's Number from RubyMonk (emphasis mine):
for a Kaprekar number k with n-digits, if you square it and add the right n digits to the left n or n-1 digits, the resultant sum is k.
Given k = 297
⇒ n = 3
⇒ k2 = 88,209
⇒ Right n digits = 209
⇒ Left n-1 digits = 88
⇒ 209 + 88 = 297
⇒ Right n digits + Left n-1 digits = k
∴ kaprekar?(297) should return true.
Your solution adds the left n digits (882), to the right n-1 (09), which is why you get false (882 + 09 ≠ 297).
A sample solution, using array slicing with negative indices, may look like:
def kaprekar?(k)
n = k.to_s.size
square = (k * k).to_s
right = square[-n..-1].to_i
left = square[0...-n].to_i
right + left == k
end

How to find largest power of 2 a number is divisible by using logic functions?

How do you find the largest power of 2 a number is divisible by using logic function
for example 144 is divisible by 16 which is 2^4.
How would one do this.
I know 144 in binary is 1001 0000 and I have to use a bitwise function.
But what would I use (and or andn orn ?) or perhaps something else and what can I use as my mask?
I know you have to look at the right most number to tell if it is divisible by 2.
Any help is appreciated
I would go with n & -n or with n & (~n + 1), in case you are worried about running across one's complement arithmetic, given the latter works with both arithmetics.
E.g.,
> 144 & (~144 + 1)
< 16
Now a short explanation.
The bitwise NOT (i.e., ~ operator) of a number n gives -(n + 1). It inverts all the bits of n. The number 2 is represented by 00000010 while its negation is 11111101 which equals to -3 (i.e., , see the two's complement representation of signed numbers).
Do not to confuse it with logical negation.
E.g., ~144 = -(144 + 1) = -145.
The bitwise AND (i.e., & operator) compares two bits of the inputs and generates a result of 1 if both are 1, otherwise it returns 0.
Now the main topic.
This is an old tricks that gives the highest power of 2 that n is divisible by. This means that it returns a number with a single one bit, specifically the bottom bit that was set in n.
For example the binary representation of 144 is 010010000. Its bottom 1 bit is the bit in fourth position (counting backward from right and starting at position 0). Thus the higher power of 2 that divides 144 is 16 (i.e., 00010000).
144 & (~144 + 1) = 144 & -144 = 16
16 & ( ~16 + 1) = 16 & - 16 = 16
10 & ( ~10 + 1) = 10 & - 10 = 2
12 & ( ~12 + 1) = 12 & - 12 = 4
11 & ( ~11 + 1) = 11 & - 11 = 1
3 & ( ~ 3 + 1) = 3 & - 3 = 1
Note that if n is not divisible by any power of 2 it returns 1.
Why it works?
The negative of n is produced by inverting its bits via ~, then adding 1 (again, see two's complement definition). This sum causes every 1 bit (starting from the bottom) to overflow until a 0 bit is encountered (let us call it the bit x). Here the overflow process stops, leaving remaining bits (those beyond the current x bit) unchanged. Thus performing & between n and its inverse will result in a binary string containing only the x bit.
An example follows.
010010000 | +144 ~
----------|-------
101101111 | -145 +
1 |
----------|-------
101110000 | -144
101110000 | -144 &
010010000 | +144
----------|-------
000010000 | 16

Algorithm to find the 'possible' combinations of variables with constraints in Matlab?

Say I have 7 items in A and 4 items in B
A=[10;40;90;130;200;260;320]
B=[100;300;500;1000]
I want to have the list of possible combinations where :
All sub-components of A MUST be included
sub-components of B can be added until the the SUM of all sub-componenets added is greater than 2000
Anyone has an idea how to do this in Matlab ?
My try :
X=sum(A);
y=1;
for Y=1:((length(A))-1);
X=X+B(y);
if(X>2000)
disp('Following is unacceptable')
end
y=y+1
end
However this code is not correct. It just adding the first element of B then adding it with the second element and so on. It isn't providing me with possible combinations.
Example :
sum(A) + B(1) = OK
sum(A) + B(4) = NOT OK
sum(A) + B(1) + B(2) = OK
sum(A) + B(2) + B(3) = OK
etc...
I want this to be automated if values of A or B change in the future. I am not sure if this is a case of probability as well.
Just use nchoosek and a double for-loop to go through all possible combinations of elements in B:
SA = sum(A);
for k = 1:numel(B)
for idx = nchoosek(1:numel(B), k)'
B_subset = B(idx);
if (SA + sum(B_subset) <= 2000)
disp([A(:)', B_subset(:)'])
end
end
end
This prints all combinations with a sum less than (or equal to) 2000. For your example we get:
10 40 90 130 200 260 320 100
10 40 90 130 200 260 320 300
10 40 90 130 200 260 320 500
10 40 90 130 200 260 320 100 300
10 40 90 130 200 260 320 100 500
10 40 90 130 200 260 320 300 500
10 40 90 130 200 260 320 100 300 500
Explanation:
The inner for-loop:
The inner for-loop uses nchoosek(1:numel(B), k), which generates all k-length combinations out of 1...length(B) (I'm using numel instead of length out of habit; in this case it has the same effect). For example, in our case B has 4 elements, so for k = 3 we get nchoosek(1:4, 3):
1 2 3
1 2 4
1 3 4
2 3 4
What we get from this is all the possible k-length combinations of indices of elements in B. In each iteration, this for-loop assigns a different combination of indices to idx. How do we convert the indices of B to real elements? We simply write B(idx).
Inside loop the combination is tested: if the total sum(A) + sum(B(idx)) is less than (or equal to) 2000, that combination is displayed.
The outer for-loop:
The outer for-loop simply iterates over all possible lengths of combinations (that is, over all possible values of k).
Hope that helps!
P.S:
Some MATLAB programming tips for the future:
1. Variable names are case-sensitive.
2. You don't need to increment the loop variable. The for loop does that automatically for you.
The best approach would involve some recursion, like this:
sumA=sum(A);
find_CombinationsOfB(B,sumA,[])
function ret=findCombinationsOfB(in_vals,total_sum,already_contained)
if total_sum>2000
ret=false;
else
for y=1:length(in_vals);
if (~findCombinationsOfB(in_vals([1:(y-1);(y+1):length(in_vals)],total_sum+in_vals(y),[already_contained in_vals(y))
display([already_contained in_vals])
end
end
ret=true;
end
Essentially what this does is tries each combination of B. It will print any that don't add up to 2000, including the sum from A.
Step by step, here's what it does:
Initially, the full array of B is passed, along with the sum of A. An empty array is passed to store which elements of B have been used so far.
Each element added in turn to the function, and called again with a new sum, and with a value missing from the array.
If at any point the array sum is over 2000, it stops that chain of reasoning.
If you want to know more about how this works, print in_vals, total_sum, and already_contained in the start of the function, like this:
fprintf("in_vals=%s total_sum=%i already_contained=%s",mat2str(in_vals),total_sum,mat2str(already_contained));
It should show you at each iteration what is happening.
Assuming B is not very long (around 10 elements), an exhaustive search through all combinations will work just fine. You can carry out this exhaustive search with a recursive function, but the code below uses a trick that's particularly concise in MATLAB: it sweeps through all combinations of the elements of B by representing each combination as a binary bit string.
% examine each of 2^length(B) combinations
for i=0:2^length(B)-1
% converts the binary string into an array of 0 and 1 used to select elements in B
combo = dec2bin(i, length(B))-'0';
% print the combination of elements if their sum is large
if combo * B + sum(A) > 2000
disp(find(combo));
end
end
There are 2^length(B) possible combinations. This examines them in turn, representing the combination as a binary string of length length(B), and evaluating the sum of these elements (with a dot product between the bit string and B).

Xnary (like binary but different) counting

I'm making a function that converts a number into a string with predefined characters. Original, I know. I started it, because it seemed fun at the time. To do on my own. Well, it's frustrating and not fun.
I want it to be like binary as in that any left character is worth more than its right neigbour. Binary is inefficient because every bit has only 1 positive value. Xnary is efficient, because a 'bit' is never 0.
The character set (in this case): A - Z.
A = 1 ..
Z = 26
AA = 27 ..
AZ = 52
BA = 53 ..
BZ = 2 * 26 (B) + 26 * 1 (Z) = 78... Right?
ZZ = 26 * 26 (Z) + 26 * 1 (Z) = 702?? Right??
I found this here, but there AA is the same as A and AAA. The result of the function is never AA or AAA.
The string A is different from AA and AAA however, so the number should be too. (Unlike binary 1, 01, 001 etc.) And since a longer string is always more valuable than a shorter... A < AA < AAA.
Does this make sense? I've tried to explain it before and have failed. I've also tried to make it before. =)
The most important thing: since A < AA < AAA, the value of 'my' ABC is higher than the value of the other script. Another difference: my script doesn't exist, because I keep failing.
I've tried with this algorithm:
N = 1000, Size = 3, (because 26 log(1000) = 2.x), so use 676, 26 and 1 for positions:
N = 1000
P0 = 1000 / 676 = 1.x = 1 = A
N = 1000 - 1 * 676 = 324
P1 = 324 / 26 = 12.x = 12 = L
N = 324 - 12 * 26 = 12
P1 = 12 / 1 = 12 = L
1000 => ALL
Sounds fair? Apparently it's crap. Because:
N = 158760, Size = 4, so use 17576, 676, 26 and 1
P0 = 158760 / 17576 = 9.x = 9 = I
N = 158760 - 9 * 17576 = 576
P1 = 576 / 676 = 0.x = 0 <<< OOPS
If 1 is A (the very first of the xnary), what's 0? Impossible is what it is.
So this one is a bust. The other one (on jsFiddle) is also a bust, because A != AA != AAA and that's a fact.
So what have I been missing for a few long nights?
Oh BTW: if you don't like numbers, don't read this.
PS. I've tried searching for similar questions but none are similar enough. The one references is most similar, but 'faulty' IMO.
Also known as Excel column numbering. It's easier if we shift by one, A = 0, ..., Z = 25, AA = 26, ..., at least for the calculations. For your scheme, all that's needed then is a subtraction of 1 before converting to Xnary resp. an addition after converting from.
So, with that modification, let's start finding the conversion. First, how many symbols do we need to encode n? Well, there are 26 one-digit numbers, 26^2 two-digit numbers, 26^3 three-digit numbers etc. So the total of numbers using at most d digits is 26^1 + 26^2 + ... + 26^d. That is the start of a geometric series, we know a closed form for the sum, 26*(26^d - 1)/(26-1). So to encode n, we need d digits if
26*(26^(d-1)-1)/25 <= n < 26*(26^d-1)/25 // remember, A = 0 takes one 'digit'
or
26^(d-1) <= (25*n)/26 + 1 < 26^d
That is, we need d(n) = floor(log_26(25*n/26+1)) + 1 digits to encode n >= 0. Now we must subtract the total of numbers needing at most d(n) - 1 digits to find the position of n in the d(n)-digit numbers, let's call it p(n) = n - 26*(26^(d(n)-1)-1)/25. And the encoding of n is then simply a d(n)-digit base-26 encoding of p(n).
The conversion in the other direction is then a base-26 expansion followed by an addition of 26*(26^(d-1) - 1)/25.
So for N = 1000, we encode n = 999, log_26(25*999/26+1) = log_26(961.5769...) = 2.x, we need 3 digits.
p(999) = 999 - 702 = 297
297 = 0*26^2 + 11*26 + 11
999 = ALL
For N = 158760, n = 158759 and log_26(25*158759/26+1) = 3.66..., we need four digits
p(158759) = 158759 - 18278 = 140481
140481 = 7*26^3 + 25*26^2 + 21*26 + 3
158759 = H Z V D
This appears to be a very standard "implement conversion from base 10 to base N" where N happens to be 26, and you're using letters to represent all digits.
If you have A-Z as a 26ary value, you can represent 0 through (26 - 1) (like binary can represent 0 - (2 - 1).
BZ = 1 * 26 + 25 *1 = 51
The analogue would be:
19 = 1 * 10 + 9 * 1 (1/B being the first non-zero character, and 9/Z being the largest digit possible).
You basically have the right idea, but you need to shift it so A = 0, not A = 1. Then everything should work relatively sanely.
In the lengthy answer by #Daniel I see a call to log() which is a red flag for performance. Here is a simple way without much complex math:
function excelize(colNum) {
var order = 0, sub = 0, divTmp = colNum;
do {
divTmp -= 26**order;
sub += 26**order;
divTmp = (divTmp - (divTmp % 26)) / 26;
order++;
} while(divTmp > 0);
var symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
var tr = c => symbols[symbols.indexOf(c)+10];
Number(colNum-sub).toString(26).split('').map(c=>tr(c)).join('');
}
Explanation:
Since this is not base26, we need to substract the base times order for each additional symbol ("digit"). So first we count the order of the resulting number, and at the same time count the substract. And then we convert it to base 26 and substract that, and then shift the symbols to A-Z instead of 0-P.

Resources