Related
So my problem, to which I have been searching a solution for hours now, is, that I have a list of list with lists of various lengths and different items:
list_1=[[160,137,99,81,78,60],[132,131,131,127,124,123],'none',[99,95,80,78]]
Now I want to change the fifth number of every list and add +1. My problem is, that I keep getting 'out of range' or other problems, because list 3 doesn't contain numbers and list 3+4 don't contain a fifth element.
I have so far found no answer to this. My first guess was adding zeros to the lists, but I'm not supposed to do that. It would also falsify the results, since then it would add +1 to any zero I have created.
Try to fix the previous post, and make minor correction, try it and ask any questions:
Any function should return the modified list, otherwise, you will not get it (unless it's supposed to do in-place changes)
You may try do List Comprehension as well, but that's more involved.
L =[[160,137,99,81,78,60],[132,131,131,127,124,123], None,[99,95,80,78]]
def addOne(L):
for lst in L:
if isinstance(lst, list) and len(lst) >= 5:
lst[4] += 1
return L
print(addOne(L))
Output:
[[160, 137, 99, 81, 79, 60], [132, 131, 131, 127, 125, 123], None, [99, 95, 80, 78]]
Assuming this is in Python,
list_1=[[160,137,99,81,78,60],[132,131,131,127,124,123],'none',[99,95,80,78]]
def addOneToFifthElement(theList):
for list_ in theList:
if type(list_)=="<class 'list'>" and len(list_)>=5:
list_[4] += 1
addOneToFifthElement(list_1)
A Google Sheet has multi-line information in its cells, e.g. address.
Each address can have a different number of lines, but we know:
1st line is always the name
Penultimate line is always the post code and city
Last line is always the country
And we are trying to split the address into 4 columns:
Name
Street address (i.e. the address left over after extracting name, post code & city, country)
Post code and city
Country
So col B (name) reads first line =REGEXEXTRACT(A1,”(\w.*)”)
Of course, I can figure out how many lines there are in each cell by counting next line character
=LEN(A1)-LEN(SUBSTITUTE(A1,CHAR(10),””))
If the formula returns 6, then there are 7 lines
How do we get columns C (street address), D (postcode and city) and E (country) formulaically?
I mean, sure, I can get country for this cell with
=REGEXEXTRACT(A2,”(\n.*){6}”)
but I can’t copy the formula over….the 6 above is manual input, which defeats the purpose. Since this is regex, it obviously can’t take cell references instead of 6, e.g.
=REGEXEXTRACT(Amazon!B4,”(\n.*){F1}”)
(if for example, I stored in column F the number of next line characters in column A)
try:
=ARRAYFORMULA(IFNA({REGEXEXTRACT(A2:A, "(.*)\n"),
REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(A2:A, "\n(.*)$", ), "\n(.*)$", ), "^(.*)\n", ),
REGEXEXTRACT(REGEXREPLACE(A2:A, "\n(.*)$", ), "(.*)$"),
REGEXEXTRACT(A2:A, "(.*)$")}))
I have a spreadsheet set up with tv program titles in column B, the next 20 or so columns are tracking different information about that title. I need to count the number of blank cells in column R relating to the range in column B that contains titles (ie, up to the first blank row in column B.)
I can easily set up a formula to count the number of empty cells in a given range in column R, the problem is as I add more titles to the sheet I would have to keep updating the range in the formula [a simple =COUNTIF(R3:R1108, "")]. I've done a little googling of the problem but haven't quite found anything that fits the situation. I thought I would be able to get the following to work but I didn't fully understand what was going on with them and they weren't giving the expected results.
I've tried these formulas:
=ArrayFormula(sum(MIN("B3:B"&MIN(IF((R3:R)>"",ROW(B3:B)-1)))))
=ArrayFormula(sum(INDIRECT("B3:B"&MIN(IF((R3:R)>"",ROW(B3:B)-1)))))
And
=if(SUM(B3:B)="","",SUM(R3:R))
All of the above formulas give "0" as the result. Based on the COUNTIF formula I have set up it should be 840, which is a number I would expect. Currently, there are 1106 rows containing data and 840 is a reasonable number to expect in this situation.
Is this what you're looking for?
=COUNTBLANK(INDIRECT(CONCATENATE("R",3,":R",(3+COUNTA(B3:B)))))
This counts the number of non-blank rows in the B column (starting at B3), and uses that to determine the rows to perform COUNTBLANK in, in column R (starting at R3). CONCATENATE is a way to give it a range by adding strings together, and the INDIRECT allows for the range reference to be a string.
a proper way would be:
=ARRAYFORMULA(COUNTBLANK(INDIRECT(ADDRESS(3, 18, 4)&":"&
ADDRESS(MAX(IF(B3:B<>"", ROW(B3:B), )), 18, 4)))
or shorter:
=ARRAYFORMULA(COUNTBLANK(INDIRECT("R3:"&
ADDRESS(MAX(IF(B3:B<>"", ROW(B3:B), )), 18, 4))))
or shorter:
=ARRAYFORMULA(COUNTBLANK(INDIRECT("R3:R"&MAX(IF(B3:B<>"", ROW(B3:B), ))))
I have an int list such as {18, 18, 18, 18, 22, 21}, I want to use Applescript to get the maximum value of this list, and get the maximum index, please teach me
There are two stages to this:
Identifying the maximum value in the list;
Once the maximum value is known, determining the index of the last occurrence of this value in the list.
I'll use a sample list I generated myself in the examples I demonstrate below. However, you can simply substitute your list for mine, and the processes described will work just as well, and produce the results specific to your input.
1. Retrieving the maximum value in a numerical list
A quick-and-dirty way to get the maxium value in the list is to use a bash numeric sort command, and pick the last item:
set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
set text item delimiters to linefeed
do shell script "sort -n <<<" & quoted form of (L as text) & "| tail -n 1"
--> 78
But, in the spirit of problem solving, the computer scientist's approach would be to iterate through the items in the list and perform these operations:
Store the first item's value.
If the next item is of greater value, then replace the currently stored value with the item we just assessed as being greater in value.
If the next item is not of greater value, retain the currently stored value.
Once you reach the end of the list, the stored value must be equal to the greatest value item in the list. At this point, we don't know its position in the list, but we know its value.
Here's the AppleScript that performs this process:
set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
set max to L's first item
repeat with x in L
if x > max then set max to x's contents
end repeat
return max
--> 78
2. Determining the index of a given item in a list
Putting aside the maximum value for now, the second half of the problem involves being able to determine the position of any given item in an ordered list.
The most obvious solution to this is, as before, iterating through each item in the list and performing this operation:
If the current item is equal to the target item, then append its index to the end of a list reserved for storing matching indices.
Once you reach the end of the list, your matched indices list will contain all the positions of the items whose value equal your target item's value; or the matched indices list will be an empty list, indicating that the main list does not contain the value we sought out.
The index of the first item in an AppleScript list is 1. Use the length property of a list to obtain the number of items in the whole list.
Here's a basic AppleScript:
set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
set matches to {}
set target to 78
repeat with i from 1 to L's length
if item i of L = the target then set end of matches to i
end repeat
return the matches
--> {3, 7, 10}
3. The combined process
Combining these two halves of the problem is as simple as running each half in sequence, being mindful to use the result from the first half of the process—the maximum value—as the target value to be sought out in the list:
set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
set max to L's first item
# Get maximum value
repeat with x in L
if x > max then set max to x's contents
end repeat
set matches to {}
set target to max
# Get index of maximum value
repeat with i from 1 to L's length
if item i of L = the target then set end of matches to i
end repeat
return the matches
--> {3, 7, 10}
Finally, as you only want the maximum index, this is simply the last value in the matches list, i.e. 10, which you obtain by replacing return the matches with this line:
return the last item in matches
--> 10
4. Efficiency improvements
Having outlined the basic methods in each process, these aren't necessarily the fastest methods. With lists containing only 10 items, inefficiency is not a noticeable concern. If you had a list of 10,000 items, you would want to be able to reduce the time to get your result.
I think I'm correct in stating that there's no discernible way to speed up the first process in terms of algorithmic improvements: retrieving the maximum value necessitates comparing every item's magnitude and retaining the largest.
Determining the index, however, can be sped up given that we only need to determine the last occurrence of an item in the list.
Therefore, we can run the process as before, but making two changes:
Start from the end of the list instead the beginning.
Stop the process once we find the first match.
Here's the script:
set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
set max to L's first item
# Get maximum value
repeat with x in L
if x > max then set max to x's contents
end repeat
set target to max
# Get index of maximum value
repeat with i from L's length to 1 by -1
if item i of L = the target then exit repeat
end repeat
return i
--> 10
Note here the second repeat loop now runs backwards from the highest index down to 1; and, we no longer require the matches list, so instead we simply exit the loop when a match is found, and see what value of i we were at.
One further improvement to the algorithm here would be to test for the null case to determine whether or not we really need to run through the list at all: the null case is the case where the list doesn't contain the value we seek. AppleScript provides a builtin way to check this:
if the target is not in L then return 0
and this line would sit immediately after set target to max and immediately before repeat with i....
5. Advanced improvements
Another way to improve efficiency, after addressing efficiency of the algorithms themselves, is to address the efficiency of the way the script is written. This is more advanced than you need to concern yourself with now, but here's how I'd probably implement the algorithms if I were writing the script for my own use:
I would define a handler called maximum() that takes a list as its argument and returns the greatest value, and I would implement the scripting of this handler like so:
on maximum(L as list)
local L
if L is {} then return {}
if L's length = 1 then return L's first item
script Array
property x0 : L's first item
property xN : rest of L
property fn : maximum(xN)
property predicate : x0 > fn
end script
tell the Array
if its predicate is true then return its x0
its fn
end tell
end maximum
This uses something called a script object to process the items of the list, which is much, much quicker in AppleScript than conventional iterative repeat loop.
Next, I would define a second handler called lastIndexOf() that takes a supplied value and a list as its two arguments, and returns the highest index at which the supplied value occurs in the given list. My handler would look like this:
on lastIndexOf(x, L as list)
local x, L
if x is not in L then return 0
if L = {} then return
script Array
property x0 : L's last item
property xN : reverse of rest of reverse of L
property predicate : x0 ≠ x
end script
# For the last match only:
if Array's predicate is false then return (Array's xN's length) + 1
# For a match list (comment out line above):
tell the Array
if its predicate is false then ¬
return the lastIndexOf(x, its xN) ¬
& (its xN's length) + 1
return lastIndexOf(x, its xN)
end tell
end lastIndexOf
Then, all I need to do to obtain the result is:
set L to {4, 24, 78, 32, 1.5, 32, 78, 14, 19, 78}
get the lastIndexOf(maximum(L), L)
--> 10
But, don't try and understand what I've done here just yet, and concentrate on understanding the repeat loop algorithms.
I've included these more advanced versions for completeness and for readers who may have wondered, had I left this out, why I didn't provide the most optimal solution I could have.
Whilst the algorithm used in these advanced versions remains the same (it doesn't look like it, but it is), the way the code is written makes these incredibly efficient for large itemed lists.
Note, however, I haven't included any error handling, so if you were to pass those handlers a list that contained non-numerical items, at least one of them would complain.
The maximum value can be determined quite easy with help of AppleScriptObjC and Key-Value Coding
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
set numberList to {18, 18, 18, 18, 22, 21, 22}
set nsNumberList to current application's NSArray's arrayWithArray:numberList
set maxValue to nsNumberList's valueForKeyPath:"#max.intValue") as integer -- 22
If there is only one occurrence of that value of if you want only the index of the first occurrence write
set maxIndex to ((nsNumberList's indexOfObject:maxValue) as integer) + 1 -- AppleScript's lists are 1-based
If there are multiple occurrences of that value and you need all indexes use a loop (unfortunately the efficient native Cocoa API indexesOfObjectsPassingTest: is not available in AppleScriptObjC)
set maxIndexes to {}
repeat with i from 0 to (count numberList) - 1 -- Cocoa's lists are 0-based
if (maxValue's isEqualToNumber:(nsNumberList's objectAtIndex:i)) then
set end of maxIndexes to i + 1
end if
end repeat
maxIndexes -- {5, 7}
Hi so I am trying to write a function hack() that takes no arguments and returns an iterator over all possible passwords.
Basically, I have to user an iterator to brute force a password. All I know from the question is that:
The password consists of three segments.
The first segment of the password is a concatenation of two words in the following list of words: ["hello", "BEGONE", "dog", "MrCool"]
The middle segment is "Donkey20"
And the last segment consists of two digits that together (i.e. 1 and 7 = 17), are no larger than 38. (And at least 0)
My method of thinking is this:
Find all the possible combinations of POSSIBLE_WORDS by using permutations(). (Find all segment 1 possibilities)
For each combination in the new list, add "Donkey20" to the end. (For example: helloBEGONEDonkey20)
Find all possible combinations between the elements in THAT list and POSSIBLE_NUMBERS.
Create an iterator that iterates over all these possible passwords, and return it
My current code only is able to do step 2, but instead of Donkey20 being at the end of each combination it's at the start. (e.g. Donkey20helloBEGONE instead of helloBEGONEDonkey20)
POSSIBLE_WORDS = ["hello", "BEGONE", "dog", "MrCool"]
MIDDLE = "Donkey20"
possible_numbers1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
possible_numbers2 = [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
possible_numbers3 = [29, 30, 31, 32, 33, 34, 35, 36, 37, 38]
POSSIBLE_NUMBERS = possible_numbers1 + possible_numbers2 + possible_numbers3
from itertools import permutations, combinations
def hack():
first_words = [''.join(word) for word in permutations(POSSIBLE_WORDS, 2)]
first_words.append(MIDDLE)
first_half = [''.join(word) for word in permutations(first_words, 2)]
Any way to fix this issue? How do I finish the remainder of the steps? Is there a different approach I could use to code this program?
Any help would be very much appreciated!
First of all, there is no reason to build up POSSIBLE_NUMBERS like that. Just use range(39) or list(range(39)) instead.
Your intention in
first_words.append(MIDDLE)
was almost certainly not to tack the single word "Donkey20" onto the end of the list of all possible first parts but was instead to tack it onto the end of each first word. I think that your intention in that part of the code can be better expressed by getting rid of that line as well as the following line and just use the single line
first_half = [word + MIDDLE for word in first_words]
When you are putting together the final possible passwords, you are going to need to turn the numbers into strings. Doubtless you already know about str() but that function has the drawback that str(1) is '1' whereas you probably want '01'. In this context, you might want to use format() since format(1,'02') returns '01'.
This should be enough of a hint to get you going. Since this seems to be homework I don't want to say any more.