C++: Find minimum in array only among elements with specified indices - python

I couldn't find a solution to the following problem:
I am trying to find the minimum in a C++ array, but without looking at all elements inside, only among elements that have a specified index.
E.g., if I am given an index k, and an array int* mylist = int[n], then I want to look for the minimal element in mylist only in a "sublist" of elements, where e.g. the index of the respective elements i fulfills i%n = k.
In Python, this can be easily solved by
min([mylist[i] for i in range(n) if i%n==k]),
but afaik, there is no equivalent in C++. Also, lambda functions do not do the trick, as far as I understood.
Any idea how to do this efficiently? Any advice would be appreciated!

This is an example of why standard algorithms work with iterators rather than directly with containers/collections. It allows you to write an iterator that embodies the indices you care about.
The problem is that writing an iterator is more work than most people would like, or consider justified for this simple of a task. Boost has some utilities to make it easier to implement iterators, such as a filter iterator, but as far as I know these are applied based only on the content of the collection, not the indices.
The code involved in creating an index_filter would be fairly trivial (e.g., should be easy to extrapolate from the code for filter_iterator linked above), but there's more boiler-plate there than most people would like. Unless you're doing things like this pretty regularly, it may be difficult to justify.

With range-v3, you may do something similar to:
for (auto e : v | ranges::view::drop(3) | ranges::view::stride(5)) {
std::cout << e << std::endl;
}
so you iterate over index 5 * k + 3.
And you can call ranges::min_element on resulting view:
auto view = v | ranges::view::drop(3) | ranges::view::stride(5);
auto it = ranges::min_element(view);
std::cout << *it << std::endl;
Demo

i % n = k will be a either:
k if k < n
[] empty that is, if k > n
This is because i varies from 0 to n
Hence there will be only one or no elements.
For clarity: n = 50; print([i%n for i in range(n)]) , gives:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
That is, unique values between 0 to n-1

Related

BubbleSort swap intermittently works

It seems sometimes this call to swap works and sometimes the return data doesn't change the array.
It seems to work with the smaller array but not the bigger one.
data = [1, 4, 5, 3, 2]
data = [1, 4, 5, 3, 2, 88, 92, 68, 22, 7,
6, 11, 44, 56, 99, 31, 32, 66, 55,
44, 77, 92, 24, 27, 14, 17, 18, 51,
69, 61, 51, 82, 84, 14, 15, 60, 70]
def Swap(a, b):
temp = a
a = b
b = temp
return {a, b}
def BubbleSort(data):
for i in range(0, len(data)-1):
for j in range(0, len(data)-1):
if data[j] > data[j+1]:
(data[j], data[j+1]) = Swap(data[j], data[j+1])
print("In data: ", data)
print("Before data: ", data)
BubbleSort(data)
print("After data: ", data)
Your Swap function returns a set, the order of which is unspecified ( implementation-defined). You probably want to return a tuple (return (a, b) or, omitting the redundant parentheses, return a, b).
But the function is unnecessary anyway. The canonical way for swapping two values in Python is
a, b = b, a
The Swap function returns a set, which has no defined order. Therefore, it is not guaranteed that it actually has the effect of swapping two items.
You probably meant to return a tuple, which is written as (a, b) or simply a, b.
Also, it is not necessary in Python to use a temporary variable to swap two values, due to tuple assignment.
The canonical way to write a swap function in Python is:
def swap(a, b):
return b, a
Note also the lower-case function name which follows the official PEP-8 style guide.

Split a list in for loop based on indices of list

This is a simplified version of some code im working on, a kind of toy model so i can focus only on the bit thats troubling me. This is why i have a function defined for finding the minimum, rather than simply using the numpy command. In my proper code, a fucntion is required, since its not as simple as using a pre-existing numpy function.
What i want to do is split my list into 2 list at the minimum point - so given what i have here, i would ideally get [15, 62, 49, 49, 4] and [100, 71, 16, 70, 62] . HOwever, i dont get this. I get all the points stored in node1, and nothing in node2. i really cant figure out why - as you can see, ive tried 2 ways of doing the for loop. i know completely the idea of the code, that the loop should run over the indices of the list and then store the values of these indices in the new lists, node1 and node2. what am i doing wrong?
#generate random list of numbers
import random
randomlist = [] #==profile_coarse
for i in range(0,10):
n = random.randint(1,100)
randomlist.append(n)
print(randomlist)
#define a function to find minimum
def get_min(list):
mini=np.min(randomlist)
return mini
node1=[]
node2=[]
for i in enumerate(randomlist):
if i<=get_min(randomlist):
node1.append(randomlist[i])
else:
node1.append(randomlist[i])
#OR
for i in range(0,len(randomlist)):
if i<get_min(randomlist):
node1.append(randomlist[i])
else:
node1.append(randomlist[i])
print(node1,node2)
which yields
[15, 62, 49, 49, 4, 100, 71, 16, 70, 62] []
you could use the built-in functions enumerate and min:
randomlist = [15, 62, 49, 49, 4, 100, 71, 16, 70, 62]
#define a function to find minimum
def get_min(l):
mini= min(enumerate(l), key=lambda x: x[1])
return mini
index_min, min_val = get_min(randomlist)
node1 = randomlist[:index_min + 1]
node2 = randomlist[index_min + 1:]
print(node1, node2)
print(node1)
print(node2)
output:
[15, 62, 49, 49, 4] [100, 71, 16, 70, 62]
enumerate returns a tuple of a a counter (by default starting at 0) and the one value from the iterable you are passing.
In your code i would be (0, 15), (1, 62)... etc.
My guess is that you simply want to do for i in randomlist
Keep in mind using a min function will in any case put all the values in one node and not in 2 as you want it to do.

Setting order in Dictionary

I am a beginner in Python . dont know how can i set the order in Dictionary? . i searched and came to know it could be done through from collections import OrderedDict but don't know how to use it. i am trying below mention code to compare two Dictionary but i am not getting the output in order .
d = { k[0]: k[1:] for k in a }
d2= { k[0]: k[1:] for k in b }
p = {i:j for i,j in d2.items() if i not in d}
q = {i:j for i,j in d.items() if i not in d2}
Any idea how to do this ?
Updated Question :
i have a nested list . How to get each list of nested list in next line ?
[['Eth116/1/12 sales connected 1 full 10G Fabric Exte'], ['Eth116/1/13 marketing connected 190 full 100 ']]
Expected Output :
Eth116/1/12 sales connected 1 full 10G Fabric Exte
Eth116/1/13 marketing connected 190 full 100
Dictionaries are unordered and there is not much you can do to change that, short of writing your own subclass of dict (not recommended). Using OrderedDict will work, as shown in hiro protagonists's comment, as long as you keep in mind that the order in an OrderedDict is the order of insertion and is not related to the values of the keys. (The same is true of the ordering of Python 3 dicts.) If a and b have the same elements but in a different order then the resulting OrderedDicts will not be equal, unless you sort a and b beforehand.
If you want to compare two dicts where you can't easily determine the order of insertion, you need a data structure that supports unordered comparisons. I didn't have your data so I had to make some up. I started with this input
>>> a
[[1, 3, 5, 7, 9], [4, 9, 14, 19, 24, 29, 34, 39], [8, 17, 26, 35, 44, 53, 62, 71], [9, 19, 29, 39, 49, 59, 69, 79, 89]]
>>> b
[[1, 3, 5, 7, 9], [4, 9, 14, 19, 24, 29, 34, 39], [8, 17, 26, 35, 44, 53, 62, 71]]
As you can see, a has one extra element beginning 9.
Modify your dictionary construction code to make the values tuples not lists, because the dict values need to be hashable for the next step to work:
>>> d = { k[0]: tuple(k[1:]) for k in a }
>>> d2= { k[0]: tuple(k[1:]) for k in b }
Then you can convert the dictionaries to sets to do an unordered comparison:
>>> s = set(d.items())
>>> s2 = set(d2.items())
>>> s == s2
False
And you can use the set operators to discover what the difference is:
>>> s2 <= s
True
>>> s - s2
set([(9, (19, 29, 39, 49, 59, 69, 79, 89))])
As of python 3.6 dictionaries are ordered in python, ignore the above answer for pythons above that number!
see here, on stackoverflow

Alternate for range in python

If I have to generate natural numbers, I can use 'range' as follows:
list(range(5))
[0, 1, 2, 3, 4]
Is there any way to achieve this without using range function or looping?
You could use recursion to print first n natural numbers
def printNos(n):
if n > 0:
printNos(n-1)
print n
printNos(100)
Based on Nihal's solution, but returns a list instead:
def recursive_range(n):
if n == 0:
return []
return recursive_range(n-1) + [n-1]
Looping will be required in some form or another to generate a list of numbers, whether you do it yourself, use library functions, or use recursive methods.
If you're not opposed to looping in principle (but just don't want to implement it yourself), there are many practical and esoteric ways to do it (a number have been mentioned here already).
A similar question was posted here: How to fill a list. Although it has interesting solutions, they're all still looping, or using range type functions.
Well, yes, you can do this without using range, loop or recursion:
>>> num = 10
>>> from subprocess import call
>>> call(["seq", str(num)])
You can even have a list (or a generator, of course):
>>> num = 10
>>> from subprocess import check_output
>>> ls = check_output(["seq", str(num)])
>>> [int(num) for num in ls[:-1].split('\n')]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42]
But...what's the purpose?

How to find the maximum number in a list using a loop?

So I have this list and variables:
nums = [14, 8, 9, 16, 3, 11, 5]
big = nums[0]
spot = 0
I'm confused about how to actually do it. I want to use this exercise to give me a starter. How do I do that on Python?
Usually, you could just use
max(nums)
If you explicitly want to use a loop, try:
max_value = None
for n in nums:
if max_value is None or n > max_value: max_value = n
Here you go...
nums = [14, 8, 9, 16, 3, 11, 5]
big = max(nums)
spot = nums.index(big)
This would be the Pythonic way of achieving this. If you want to use a loop, then loop with the current max value and check if each element is larger, and if so, assign to the current max.
nums = [14, 8, 9, 16, 3, 11, 5]
big = None
spot = None
for i, v in enumerate(nums):
if big is None or v > big:
big = v
spot = i
Python already has built in function for this kind of requirement.
list = [3,8,2,9]
max_number = max(list)
print (max_number) # it will print 9 as big number
however if you find the max number with the classic vay you can use loops.
list = [3,8,2,9]
current_max_number = list[0]
for number in list:
if number>current_max_number:
current_max_number = number
print (current_max_number) #it will display 9 as big number
Why not simply using the built-in max() function:
>>> m = max(nums)
By the way, some answers to similar questions might be useful:
Pythonic way to find maximum value and its index in a list?
How to find all positions of the maximum value in a list?
To address your second question, you can use a for loop:
for i in range(len(list)):
# do whatever
You should note that range() can have 3 arguments: start, end, and step. Start is what number to start with (if not supplied, it is 0); start is inclusive.. End is where to end at (this has to be give); end is exclusive: if you do range(100), it will give you 0-99. Step is also optional, it means what interval to use. If step is not provided, it will be 1. For example:
>>> x = range(10, 100, 5) # start at 10, end at 101, and use an interval of 5
>>> x
[10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] # note that it does not hit 100
Since end is exclusive, to include 100, we could do:
>>> x = range(10, 101, 5) # start at 10, end at 101, and use an interval of 5
>>> x
[10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100] # note that it does hit 100
For the Max in List Code HS I've managed to get most of the auto grader to work for me using this code:
list = [-3,-8,-2,0]
current_max_number = list[0]
for number in list:
if number>current_max_number:
current_max_number = number
print current_max_number
def max_int_in_list():
print "Here"
I'm not sure where the max_int_in_list goes though. It needs to have exactly 1 parameter.
To print the Index of the largest number in a list.
numbers = [1,2,3,4,5,6,9]
N = 0
for num in range(len(numbers)) :
if numbers[num] > N :
N = numbers[num]
print(numbers.index(N))
student_scores[1,2,3,4,5,6,7,8,9]
max=student_scores[0]
for n in range(0,len(student_scores)):
if student_scores[n]>=max:
max=student_scores[n]
print(max)
# using for loop to go through all items in the list and assign the biggest value to a variable, which was defined as max.
min=student_scores[0]
for n in range(0,len(student_scores)):
if student_scores[n]<=min:
min=student_scores[n]
print(min)
# using for loop to go through all items in the list and assign the smallest value to a variable, which was defined as min.
Note: the above code is to pick up the max and min by using for loop, which can be commonly used in other programming languages as well. However, the max() and min() functions are the easiest way to use in Python to get the same results.
I would add this as a reference too. You can use the sort and then print the last number.
nums = [14, 8, 9, 16, 3, 11, 5]
nums.sort()
print("Highest number is: ", nums[-1])
scores = [12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27,
28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 31, 31, 37,
56, 75, 23, 565]
# initialize highest to zero
highest = 0
for mark in scores:
if highest < mark:
highest = mark
print(mark)

Categories