How can I clean up this code to be shorter? [duplicate] - autoit

This question already has answers here:
Incremental variable definition
(2 answers)
Closed 4 years ago.
I'm using AutoIt:
$1 = GetItemBySlot(1, 1)
$2 = GetItemBySlot(1, 2)
$3 = GetItemBySlot(1, 3)
$4 = GetItemBySlot(1, 4)
$5 = GetItemBySlot(1, 5)
The code repeats for 40 lines. How can I shorten it?

You could shorten this by using Assign() and
Eval().
For $i = 1 To 5
Assign($i, GetItemBySlot(1, $i))
Next
That would be 3 lines instead of n lines. During runtime this will be expanded to:
Assign(1, GetItemBySlot(1, 1))
Assign(2, GetItemBySlot(1, 2))
Assign(3, GetItemBySlot(1, 3))
Assign(4, GetItemBySlot(1, 4))
Assign(5, GetItemBySlot(1, 5))
To get the data of those variables you need to use the Eval function. So
For $i = 1 To 5
Eval($i)
Next
returns the value of GetItemBySlot(1, $i).

For $i = 1 To 40
$aItemsBySlot[$i] = GetItemBySlot(1, $i)
Next
As per Documentation - Intro - Arrays:
An Array is a variable containing a series of data elements. Each element in this variable can be accessed by an index number which relates to the position of the element within the Array - in AutoIt the first element of an Array is always element [0]. Arrays elements are stored in a defined order and can be sorted.
Example in GetItemBySlotMulti() (untestes, no error-checking):
Global $aItems
; Assign:
$aItems = GetItemBySlotMulti(1, 40)
; Retrieve single value (output item #1 to console):
ConsoleWrite($aItems[1] & #CRLF)
; Retrieve all values:
For $i = 1 To $aItems[0]
ConsoleWrite($aItems[$i] & #CRLF)
Next
; Retrieve amount of items:
ConsoleWrite($aItems[0] & #CRLF)
; Re-assign a single value (re-assign item #1):
$aItems[1] = GetItemBySlot(1, 1)
; Function (used to assign example):
Func GetItemBySlotMulti(Const $iSlot, Const $iItems)
Local $aItemsBySlot[$iItems +1]
$aItemsBySlot[0] = $iItems
For $i = 1 To $iItems
$aItemsBySlot[$i] = GetItemBySlot($iSlot, $i)
Next
Return $aItemsBySlot
EndFunc
Related.

Related

Right Shift and Left shift operator in Classic ASP

How to use Right Shift operator in classic ASP. As suggested in In ASP, Bit Operator Left shift and Right shift , I used "\" for right shift operator. it gives me wrong result.
For example
in javascript, 33555758 >> 24 gives result 2.
But in Classic ASP 33555758 \ 24 gives division result.
Please help me on this.
Bitwise right shift >> is not equal to simple division \ by the given number, but by the given number of times by integer 2, which is binary 10. A bit shift moves each digit in a set of bits right. I.e. dividing by binary 10 removes a binary digit from the number and shifts digits right.
Example: 5 >> 1 = 2
5 00000000000000000000000000000101
5 >> 1 00000000000000000000000000000010 (2)
which is same as 5 / 2,
i.e. in your case it will be not 33555758 \ 24 but 24 times dividing 2. As there is no direct method in vbscript, it can be done as
Function SignedRightShift(pValue, pShift)
Dim NewValue, PrevValue, i
PrevValue = pValue
For i = 1 to pShift
Select Case VarType(pValue)
Case vbLong
NewValue = Int((PrevValue And "&H7FFFFFFF") / 2)
If PrevValue And "&H80000000" Then NewValue = NewValue Or "&HC0000000"
NewValue = CLng(NewValue)
Case vbInteger
NewValue = Int((PrevValue And "&H7FFF") / 2)
If PrevValue And "&H8000" Then NewValue = NewValue Or "&HC000"
NewValue = CInt("&H"+ Hex(NewValue))
Case vbByte
NewValue = Int(PrevValue / 2)
If PrevValue And "&H80" Then NewValue = NewValue Or "&HC0"
NewValue = CByte(NewValue)
Case Else: Err.Raise 13 ' Not a supported type
End Select
PrevValue = NewValue
Next
SignedRightShift = PrevValue
End Function
and used as
x = SignedRightShift(33555758, 24)
For more, see http://chris.wastedhalo.com/2014/05/more-binarybitwise-functions-for-vbscript/

Map, reduce, filter apply to for loops and while loops

I'm new to Julia and learning use of Map, reduce, filter.
It is becoming very hard for me to comprehend how it can replace for and while loops.
For ex for below code, I would like to replace for loop
function addMultiplesOf3And5(N::Int)
sumOfMultiples = 0
if(N == 3)
return sumOfMultiples + N
end
for i = 3:N-1
if(i % 3 == 0 && i % 5 == 0)
continue
elseif(i % 3 == 0)
sumOfMultiples += i
elseif(i % 5 == 0)
sumOfMultiples += i
end
end
return sumOfMultiples
end
I would really appreciate the help.
Update :
This is what I did after going through tutorials
function addMultiplesOf3And5(N::Int)
array = range(1,N-1)
return reduce(+, map(x -> multiples_of_3_Or_5(x), array))
end
function multiples_of_3_Or_5(n)
if(n % 3 == 0 && n % 5 == 0)
return 0
elseif(n % 3 == 0)
return n
elseif(n % 5 == 0)
return n
else
return 0
end
end
Final:
function addMultiplesOf3And5(N::Int)
array = range(1,N-1)
return reduce(+, filter(x -> ((x%3==0)$(x%5==0)), array))
end
To understand how you can replace your 'for loop + if block' code with 'map / reduce / filter' you need to know exactly how they work and why they might be chosen instead.
1. The map function
map is a function that takes a function variable and a list as arguments, and returns a new list, where each element is the result of applying the function to each element of the old list. So for example if your variable f refers to a function f(x) = x + 5 you defined earlier, and you have a list L=[1,2,3,4,5], then map(f, L) will return [f(L[1]), f(L[2]), f(L[3]), f(L[4]), f(L[5])]
So if you have code like:
f(x) = x + 5;
L = [1,2,3,4,5];
A = zeros(5);
for i in L
A[i] = f(i);
end
You could rewrite this as a mapping operation like so:
A = map(x -> x + 5, [1,2,3,4,5]);
2. The reduce function
reduce takes a binary function variable (i.e. a function that takes two arguments) and a list as arguments. What it does is probably best explained by an example. Calling reduce with the + operator, and list [1,2,3,4,5] will do the following:
Step 1: [1, 2, 3, 4, 5] % : 5 elements
Step 2: [1+2, 3, 4, 5] % [3,3,4,5] : 4 elements
Step 3: [3+3, 4, 5] % [6, 4, 5] : 3 elements
Step 4: [6+4, 5] % [10, 5] : 2 elements
Step 5: [10+5] % [15] : 1 elements
result: 15
i.e. we have reduced the list to a single result by successively applying the binary function to the first pair of elements, consuming the list little by little.
So if you have code like:
f(x,y) = x + y
L = [1,2,3,4,5];
A = L[1];
for i in 2:length(L)
A = f(A, L[i])
end
you could rewrite this as a reduce operation like so:
A = reduce(x,y -> x+y, [1,2,3,4,5])
3. The filter function
filter takes a predicate function (e.g. iseven, isnull, ==, or anything that takes an argument and performs a test on it, resulting in true or false) and a list, tests each element of the list with the function and returns a new list that only contains the elements that pass that test. e.g.
filter(iseven, [1,2,3,4,5]) # returns [2,4]
The answer to your problem
If I understand correctly, addMultiplesOf3And5 takes a number N (e.g. 20), and does the following:
filter out all the elements that can be divided by either 3 or 5 from the list [1,2,3,...,20]
successively add all elements of the resulting list together using a reduce function.
You should be able to use the above to figure out the exact code :)
Not sure what the function in the question is supposed to calculate, but:
addMult3or5(N) = N==3 ? 3 : sum(filter(x->((x%3==0)$(x%5==0)),3:N-1))
calculates the same thing.
sum is a a reduce-like function for the + operation.
Hope this helps clarify.
Also, $ is the exclusive-or operation in Julia.

Longest substring in alphabetical order [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Write a program that prints the longest substring of s in which the letters occur in alphabetical order. For example, if s = 'azcbobobegghakl', then your program should print
Longest substring in alphabetical order is: beggh
In the case of ties, print the first substring. For example, if s = 'abcbcd', then your program should print
Longest substring in alphabetical order is: abc
Here you go edx student i've been helped to finish the code :
from itertools import count
def long_sub(input_string):
maxsubstr = input_string[0:0] # empty slice (to accept subclasses of str)
for start in range(len(input_string)): # O(n)
for end in count(start + len(maxsubstr) + 1): # O(m)
substr = input_string[start:end] # O(m)
if len(substr) != (end - start): # found duplicates or EOS
break
if sorted(substr) == list(substr):
maxsubstr = substr
return maxsubstr
sub = (long_sub(s))
print "Longest substring in alphabetical order is: %s" %sub
These are all assuming you have a string (s) and are needing to find the longest substring in alphabetical order.
Option A
test = s[0] # seed with first letter in string s
best = '' # empty var for keeping track of longest sequence
for n in range(1, len(s)): # have s[0] so compare to s[1]
if len(test) > len(best):
best = test
if s[n] >= s[n-1]:
test = test + s[n] # add s[1] to s[0] if greater or equal
else: # if not, do one of these options
test = s[n]
print "Longest substring in alphabetical order is:", best
Option B
maxSub, currentSub, previousChar = '', '', ''
for char in s:
if char >= previousChar:
currentSub = currentSub + char
if len(currentSub) > len(maxSub):
maxSub = currentSub
else: currentSub = char
previousChar = char
print maxSub
Option C
matches = []
current = [s[0]]
for index, character in enumerate(s[1:]):
if character >= s[index]: current.append(character)
else:
matches.append(current)
current = [character]
print "".join(max(matches, key=len))
Option D
def longest_ascending(s):
matches = []
current = [s[0]]
for index, character in enumerate(s[1:]):
if character >= s[index]:
current.append(character)
else:
matches.append(current)
current = [character]
matches.append(current)
return "".join(max(matches, key=len))
print(longest_ascending(s))
The following code solves the problem using the reduce method:
solution = ''
def check(substr, char):
global solution
last_char = substr[-1]
substr = (substr + char) if char >= last_char else char
if len(substr) > len(solution):
solution = substr
return substr
def get_largest(s):
global solution
solution = ''
reduce(check, list(s))
return solution

R while loop and number of times

got a while loop going, and that's working fine.
However I also need to add another condition.
I need the loop to keep going until it satisfies the while loop, but then I also need to add that this can only get repeated x times.
I think you would have to make a for loop to do x times, is it possible to put a while loop in this?
Basically how can I make a loop either reach the goal or stop after x loops??
The expression in while needs to be TRUE for the loop to continue. You can use | or & to add extra conditions. This loop runs 99 times or until sum of random variables is less than 100.
counter <- 0
result <- 0
while(counter < 100 | sum(result) < 100) {
result <- sum(result, rnorm(1, mean = 5, sd = 1))
counter <- sum(counter, 1)
}
> result
[1] 101.5264
> counter
[1] 21
Just pass the current iterator value as an argument to your function. That way you can break the recursion if that reaches a particular value.
But why do you have a while loop if you use recursion, for example:
add_one_recursive = function(number) {
number = number + 1
cat("New number = ", number, "\n")
if(number > 10) {
return(number)
} else {
return(add_one_recursive(number))
}
}
final_number = add_one_recursive(0)
New number = 1
New number = 2
New number = 3
New number = 4
New number = 5
New number = 6
New number = 7
New number = 8
New number = 9
New number = 10
New number = 11
Does not require an explicit loop at all.

Can Do While Loop stop when counter reaches X

I want to edit some legacy code written in classic-ASP.
Currently I've got a subroutine declared that uses a for-next loop to output some radio buttons:
For i = 1 to Cols
response.write "blah"
...
Next
i is simply a counter, Cols is a value passed to the sub-routine. I tried editing the for-loop to be a while loop instead:
i = Start
do while i <= Cols
response.write "blah"
...
i = i + 1
loop
But I get a Response Buffer Limit Exceeded error. If I replace Cols with the value it works fine. Is this a limitation in classic-ASP?
Reason I want to use a do while loop is because currently the sub-routine is limited to looping from 1 to Cols. It would be helpful to sometimes specify the loop counts backwards (i.e. step -1) but I can't write:
if Direction = Backwards then
For i = Cols to 1 step -1
else
For i = 1 to Cols
end if
How about:
If Direction = Backwards Then
cs = 10
ce = 1
s = -1
Else
cs = 1
ce = 10
s = 1
End If
For i = cs To ce Step s
''
Next

Resources