Range function in M? - excel

Is it possible to create a numerical range in M? For example something like:
let
x = range(1,10) // {1,2,3,4,5,6,7,8,9,10}, from 1 to 10, increment by 1
x = range(1,10,2) // {1,3,5,7,9}, from 1 to 10, increment by 2

For simple scenarios, a..b might be appropriate. Some examples:
let
firstList = {1..10}, // {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
secondList = {1, 5, 12, 14..17, 18..20}, // {1, 5, 12, 14, 15, 16, 17, 18, 19, 20}
thirdList = {Character.ToNumber("a")..100, 110..112}, // {97, 98, 99, 100, 110, 111, 112}
fourthList = {95..(10 * 10)} // {95, 96, 97, 98, 99, 100}
in
fourthList
Otherwise, maybe try a custom function which internally uses List.Generate:
let
range = (inclusiveStart as number, inclusiveEnd as number, optional step as number) as list =>
let
interval = if step = null then 1 else step,
conditionFunc =
if (interval > 0) then each _ <= inclusiveEnd
else if (interval < 0) then each _ >= inclusiveEnd
else each false,
generated = List.Generate(() => inclusiveStart, conditionFunc, each _ + interval)
in generated,
firstList = range(1, 10), // {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
secondList = range(1, 10, 2), // {1, 3, 5, 7, 9}
thirdList = range(1, 10 , -1), // {} due to the combination of negative "step", but "inclusiveEnd" > "inclusiveStart"
fourthList = range(10, 1, 0), // {} current behaviour is to return an empty list if 0 is passed as "step" argument.
fifthList = range(10, 1, -1), // {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}
sixthList = range(10, 1, 1) // {} due to the combination of positive "step", but "inclusiveEnd" < "inclusiveStart"
in
sixthList
The above range function should be able to generate both ascending and descending sequences (see examples in code).
Alternatively, you could create a custom function which uses List.Numbers internally by first calculating what the count argument needs to be. But I chose to go with List.Generate.

Related

How to make this code loop through the dictionary to create another dictionary

I wish to create a dictionary which is a summary of a dictionary describing temperatures in Prague. The code below correctly extracts the first key: value pair. The issue is how to get all key: value pairs like this:
sum_dict = {1775: 4, 1778: 16, 1781: 7, ...}
test_dict= {1775: 3, 1776: 1, 1778: 3, 1779: 12, 1780:1,
1781: 5, 1782: 2, 1784: 8, 1786: 3, 1787: 4}
sum = 0
for key, value in test_dict.items():
years = list(range(1775, 1778))
for year in years:
if key == year:
sum = value + sum
# Create dictionary pair with 1st date in years and sum
the values
sum_dict = {}
sum_dict[years[0]] = sum
print(sum_dict)
years = [a+3 for a in years]
print(years)
Try:
test_dict = {
1775: 3,
1776: 1,
1778: 3,
1779: 12,
1780: 1,
1781: 5,
1782: 2,
1784: 8,
1786: 3,
1787: 4,
}
_min, _max = min(test_dict), max(test_dict)
sum_dict = {
year: sum(test_dict.get(y, 0) for y in range(year, year + 3))
for year in range(_min, _max, 3)
}
print(sum_dict)
Prints:
{1775: 4, 1778: 16, 1781: 7, 1784: 11}

Dynamic programming best sum code in python

I am trying to learn dynamic programming by followin an online video. The original video is using javascript and I am trying to use python to implement the same. However, I am not able to locate the error in my python implementation.
The question is as follows
write a fn. bestsum(targetsum, numbers) that takes in a targetsum and
an array of numbers as arguments.
The fn. should return an array containing the shortest combination of
numbers that add up to exactly the targetsum.
If there is a tie for the shortest combination, you may return any of
the shortest.
The javascript implementation is as follows.
const bestSum = (targetSum, numbers, memo={}) => {
if (targetSum in memo) return memo[targetSum];
if (targetSum === 0) return [];
if (targetSum < 0) return null;
let shortest_com = null;
for (let num of numbers) {
const remainder = targetSum - num;
const remainder_com = bestSum(remainder, numbers, memo);
if (remainder_com !== null) {
const combination = [...remainder_com, num];
if (shortest_com === null || combination.length < shortest_com.length) {
shortest_com = combination;
}
}
}
memo[targetSum] = shortest_com
return shortest_com;
};
console.log(bestSum(7, [5, 3, 4, 7]));
console.log(bestSum(8, [2, 3, 5]));
console.log(bestSum(8, [1, 4, 5]));
console.log(bestSum(100, [1, 2, 5, 25]));
Python code I implemented is
from typing import Any, Dict, List, Optional
def best_sum(target: int, numbers: List[int], memo:Dict[int, Any]={}) -> Optional[List[int]]:
if target in memo.keys():
return memo.get(target)
if target == 0:
return []
if target < 0:
return None
shortest_combination: Optional[List] = None
for num in numbers:
partial = best_sum(target=target - num, numbers=numbers, memo=memo)
if partial != None:
print(num)
partial.append(num)
if (shortest_combination == None) or (len(partial) < len(shortest_combination)):
shortest_combination = partial
memo[target] = shortest_combination
return shortest_combination
if __name__ == "__main__":
print(best_sum(target=100, numbers=[1, 2, 5, 25]))
For the test case: target=100, numbers=[1, 2, 5, 25].
Javascript implementation gives.
[ 25, 25, 25, 25 ]
But Python gives.
[25, 1, 1, 2, 1, 2, 1, 2, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25]
The problem is in this snippet:
if partial != None:
partial.append(num)
if (shortest_combination == None) or (len(partial) < len(shortest_combination)):
shortest_combination = partial
The Javascript appoach creates a copy of the list remainder_com with the element num appended. In your approach, you're appending to partial directly without creating a copy. Thus, in every iteration the same list will be used to modifications, which is not desired. Change it to
# Creates a copy of `partial` with `num` appended
combination = partial[:] + [num]
if (shortest_combination == None) or (len(combination) < len(shortest_combination)):
shortest_combination = combination
This outputs [25, 25, 25, 25] as expected.

how do I repeat the codes in the function N times instead of re-typing it?

def append_sum(lst):
new_num = (lst[-1]+lst[-2])
lst.append(new_num)
new_num1 = (lst[-1]+lst[-2])
lst.append(new_num1)
new_num2 = (lst[-1]+lst[-2])
lst.append(new_num2)
return lst
print(append_sum([1, 1, 2]))
this prints [1, 1, 2, 3, 5, 8] but how do I do it N times?
And what is this "codes" actually called in coding? (I'm referring to the code that is in the function)
You can do that single operation N times just by doing:
for _ in range(N):
lst.append(lst[-1] + lst[-2])
A full example:
def append_sum(lst, count):
for _ in range(count):
lst.append(lst[-1] + lst[-2])
return lst
print(append_sum([1, 1], 10))
will generate:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

taking averages of certain indices using another list in python

I was hoping to take the average of a list using another list with the start and stop indices.
for example:
a = [3, 9]
b = [0, 1, 12, 9, 0, 8, 9, 3, 3, 5, 7, 1, 4, 6, 6]
I want to take the average of the numbers from b[3] to b[9] and this is what I have so far
counter = a[0]
sum = b[counter]
while counter < a[1] + 1:
counter += 1
sum = sum + b[counter]
denominator = a[1] - a[0] + 1
avg = sum/denominator
But after checking, it seems to be giving the wrong thing
you could use statistics.mean
from statistics import mean
a = [3, 9]
b = [0, 1, 12, 9, 0, 8, 9, 3, 3, 5, 7, 1, 4, 6, 6]
mean(b[a[0]: a[1] + 1])
or you could use:
sum(b[a[0]: a[1] + 1]) / len(b[a[0]: a[1] + 1])
I would suggest the following:
from statistics import mean
a = [3, 9]
b = [0, 1, 12, 9, 0, 8, 9, 3, 3, 5, 7, 1, 4, 6, 6]
avg = mean(b[a[0]:a[1]+1])
print (avg)

How to find larger numbers of any selected number in a series in an ascending order in NumPy?

I have a series of randomly scrabbled numbers. I want to pick a number (say X), and then find and write larger numbers than X in an ascending order. I’m using Python and NumPy.
EXAMPLE:
Series of random numbers:
4, 8, 5, 9, 3, 11, 17, 19, 9, 15, 16
X=4, Then:
4, 8, 9, 11, 17, 19
X=8, Then:
8, 9, 11, 17, 19
X=3, Then:
3, 11, 17, 19
Please note that when we pick X, our desire is to put X at the beginning of the ascending series, meaning that the count should start from X.
Also note that we don’t want to sort the numbers in terms of their position. No position change in the numbers. Only reading and writing the numbers in an ascending order. Next numbers in the sequence that are smaller than X should be ignored. Thank you.
EDIT:
def get_elements(get_from,get_by):
return [ (get_from[i], i ) for i in range(len(get_from)) if get_by[i] == 0 ]
def ordered_position():
ordered_lst = [0] *len(data_arr)
new_val = 1
while True:
print(new_val)
ge = get_elements(data_arr,ordered_lst)
if new_val >= len(data_arr) or not ge: break
first_val, idx_fist_val = ge.pop(0)
ordered_lst[idx_fist_val] = (first_val,new_val)
for item, idx in ge:
if data_arr[idx] >= first_val:
ordered_lst[idx] = (first_val,new_val)
first_val = item
new_val += 1
return ordered_lst
You can use np.maximum.accumulate like so::
a = np.array([4, 8, 5, 9, 3, 11, 17, 19, 9, 15, 16])
X = 4
withreps = np.maximum.accumulate(a[np.argmax(a==X):])
result = withreps[np.where(np.diff(withreps, prepend=withreps[0]-1))]
result
# array([ 4, 8, 9, 11, 17, 19])

Resources