Finding a next lowest number from a List in python - python

I have a list of arrays as follows:
Array =[3, 6, 5, 7, 2, 4, 3, 5, 4, 5, 4, 7, 6, 7, 1, 7, 4, 6, 3]
example:
Value = 3, 6, 5, 7, 2, 4, 3, 5, 4, 5, 4, 7, 6, 7, 1, 7, 4, 6, 3
valley/Peak = v, p, v, p, v, p, v, p, v, p, v, p, v, p, v, p, v, p,v

As Mark Ransom & SA.93 suggested, indexing in python starts from 0. Maybe you are more familiar with R... :) For your solution, try this;
def next_lowest_num(Array,num):
lst = []
for i in Array[Array.index(num):]:
if i >= num:
lst.append(i)
else:
lst.append(i)
break
return lst
print(next_lowest_num(Array=[3, 6, 5, 7, 2, 4, 3, 5, 4, 5, 4, 7, 6, 7, 1, 7, 4, 6, 3],num=3))
print(next_lowest_num(Array=[3, 6, 5, 7, 2, 4, 3, 5, 4, 5, 4, 7, 6, 7, 1, 7, 4, 6, 3],num=5))
# Output
[3, 6, 5, 7, 2]
[5, 7, 2]
Hope this Helps...

logic
assign the index to start from
assign the value of the starting index
make a loop starting from the starting index to the end of the loop
in the loop check if current number is smaller than the starting target
slice the list to create the result sublist
code
array = [3, 6, 5, 7, 2, 4, 3, 5, 4, 5, 4, 7, 6, 7, 1, 7, 4, 6, 3]
start_index = 0 # the index to start from
# start_index = int(input("Enter the index to start from: ")) # to take this a step further, you could ask the user for the index to start from
target = array[start_index] # the number in the starting index
for i in range(start_index, len(array)): # loop from the start index till the end
if array[i] < target: # if the current number is smaller than my traget
# split the list from the start index to the current index (+1 because the slice is not inclusive)
print(array[start_index:i+1])
break
if i == len(array)-1: # if we reached the end of the list
print('fail') # print the rest of the list
input
start_index = 0
array = [3, 6, 5, 7, 2, 4, 3, 5, 4, 5, 4, 7, 6, 7, 1, 7, 4, 6, 3]
output
[3, 6, 5, 7, 2]

Related

(Sudoku board validator) loop through every n item in couple lists

I'm trying to make a sudoku board validator and I'm stuck at validating columns.
Grid looks like this:
[1,2,3,4,5,6,7,8,9]
[5,5,5,5,5,5,5,5,8]
[5,5,5,5,5,5,5,5,7]
[5,5,5,5,5,5,5,5,6]
[5,5,5,5,5,5,5,5,5]
[5,5,5,5,5,5,5,5,4]
[5,5,5,5,5,5,5,5,3]
[5,5,5,5,5,5,5,5,2]
[5,5,5,5,5,5,5,5,1]
I've came up with an idea
to loop through every n item in rows, put them in list and by using set() check if all numbers are unique (9 times).
My code looks like this:
def grid(*rows):
#validate columns
cut = []
x = range(0,8)
counter = 0
while counter != 9:
for column in rows:
cut.append(column[x])
print(len(cut) == len(set(cut)))
counter += 1
I suspect there are better and more efficient ways to solve this problem, but I'm new to Python and want to learn. If I want to make it my way, what am I doing wrong?
If I want to make it my way, what am I doing wrong?
you initialize cut = [] in front of both loops instead of initializing it every time a new column is validated. You have to place cut = [] within the while and before the for loop going over the rows to prevent the code of collecting in cut all of the extracted values and not only these from the just validated column.
x = range(0,8) makes x being a range not a single value required as index, so the code column[x] gives an TypeError: list indices must be integers or slices, not range. You don't need x in your code at all. The value of counter is what you need in place of x.
print and counter+1 indentation is wrong. In your code the counter will be increased not only with each new processed column, but also with each row from which the single column value is extracted. This will give counter values from 0 up to 80 and not as expected and should be from 0 to 8.
a better approach to sudoku validation will be one validation procedure applied to the three different views on the sudoku grid. For a proposal of code providing functions for generating a column and 3x3 cell view on the sudoku grid generated from the list of rows see the code provided later on along with a proposal of another principle for use in the validation function.
Below your code adjusted in a way that it works as it should:
def grid(rows):
#validate columns
counter = 0
while counter != 9:
cut = []
for row in rows:
cut.append(row[counter])
counter += 1
print(len(cut) == len(set(cut)))
To get you started using another approach for the logic of a validation procedure, below a suggestion how to get the column and the 3x3 cell views on the sudoku grid list from the list of the grid rows. Having this views the function for validating the columns and the 3x3 cells will be exactly the same as for rows.
The naming of variables in the code should be sufficient as documentation what the code does:
lstSudokuGridRows = [
[6, 2, 5, 8, 4, 3, 7, 9, 1],
[7, 9, 1, 2, 6, 5, 4, 8, 3],
[4, 8, 3, 9, 7, 1, 6, 2, 5],
[8, 1, 4, 5, 9, 7, 2, 3, 6],
[2, 3, 6, 1, 8, 4, 9, 5, 7],
[9, 5, 7, 3, 2, 6, 8, 1, 4],
[5, 6, 9, 4, 3, 2, 1, 7, 8],
[3, 4, 2, 7, 1, 8, 5, 6, 9],
[1, 7, 8, 6, 5, 9, 3, 4, 2]]
print(lstSudokuGridRows)
def getSudokuGridColumns(lstSudokuGridRows):
return list(zip(*lstSudokuGridRows))
lstSudokuGridColumns = getSudokuGridColumns(lstSudokuGridRows)
print(lstSudokuGridColumns)
def getSudokuGridCells(lstSudokuGridRows):
lstCells = [[],[],[],[],[],[],[],[],[]]
#print(lstCells)
for i_row, row in enumerate(lstSudokuGridRows):
for i_column, col_row_item in enumerate(row):
#print(3*(i_row//3)+(1+i_column//3)-1, end='|')
lstCells[3*(i_row//3)+(1+i_column//3)-1].append(col_row_item)
#print()
return lstCells
lstSudokuGridCells = getSudokuGridCells(lstSudokuGridRows)
print(lstSudokuGridCells)
and the printed output can be checked against the sudoku grid defined as a list of rows if the correct values are in the 9 sublists of the list:
[[6, 2, 5, 8, 4, 3, 7, 9, 1], [7, 9, 1, 2, 6, 5, 4, 8, 3], [4, 8, 3, 9, 7, 1, 6, 2, 5], [8, 1, 4, 5, 9, 7, 2, 3, 6], [2, 3, 6, 1, 8, 4, 9, 5, 7], [9, 5, 7, 3, 2, 6, 8, 1, 4], [5, 6, 9, 4, 3, 2, 1, 7, 8], [3, 4, 2, 7, 1, 8, 5, 6, 9], [1, 7, 8, 6, 5, 9, 3, 4, 2]]
[(6, 7, 4, 8, 2, 9, 5, 3, 1), (2, 9, 8, 1, 3, 5, 6, 4, 7), (5, 1, 3, 4, 6, 7, 9, 2, 8), (8, 2, 9, 5, 1, 3, 4, 7, 6), (4, 6, 7, 9, 8, 2, 3, 1, 5), (3, 5, 1, 7, 4, 6, 2, 8, 9), (7, 4, 6, 2, 9, 8, 1, 5, 3), (9, 8, 2, 3, 5, 1, 7, 6, 4), (1, 3, 5, 6, 7, 4, 8, 9, 2)]
[[6, 2, 5, 7, 9, 1, 4, 8, 3], [8, 4, 3, 2, 6, 5, 9, 7, 1], [7, 9, 1, 4, 8, 3, 6, 2, 5], [8, 1, 4, 2, 3, 6, 9, 5, 7], [5, 9, 7, 1, 8, 4, 3, 2, 6], [2, 3, 6, 9, 5, 7, 8, 1, 4], [5, 6, 9, 3, 4, 2, 1, 7, 8], [4, 3, 2, 7, 1, 8, 6, 5, 9], [1, 7, 8, 5, 6, 9, 3, 4, 2]]
For validation of the board I would suggest not to implement the idea of the number of unique elements as the not yet solved sudoku board can have also the zero ( 0 ) as value or just wrong values beyond the span of 1 to 9 what will then be not detected by the validation and therefore making it much harder to debug the code in eventual case of problems. Below a proposal of validation function based on comparing a sorted line of the sudoku grid view (which can be one of row view, column view and 3x3 cell view) with [1,2,3,4,5,6,7,8,9]:
def validateSudokuView(lstSudokuGridView):
gridViewOK = True
for line in lstSudokuGridView:
if sorted(line) != [1,2,3,4,5,6,7,8,9]:
gridViewOK = False
break
return gridViewOK
which can be also coded as:
def validateSudokuView(lstSudokuGridView):
return all(sorted(line)==[1,2,3,4,5,6,7,8,9] for line in lstSudokuGridView)
using the Python all() function.
You can use zip to transpose the matrix, then check the size of the sets while iterating over the columns.
for col in zip(*rows):
if len({*col}) != len(col):
print('not unique')
else:
print('good')

Randomly generate a 9 × 9 list where the entries are integers between 1 and 9 with no repeat entries in any row or in any column

I wrote a code for :Randomly generate a 9 × 9 list where the entries are integers between 1 and 9 with no repeat entries in any row or in any column.
but my code does not solve the no repeat entry part.
matr=[ ]
#print(matr)
for i in range(9):
entry=[ ]
for j in range(9):
while len(entry)<9:
draw=randint(1,9)
while draw not in entry:
entry.append(draw )
matr.append(entry )
#print(matr )
#print(entry)
for i in matr:
print(i)
or this code:
print('--------list 1 to 9--------------------------------------')
list=[ i for i in range(1,10) ]
print(list)
print('---------shuffle list-------------------------------------')
matr=[ ]
entry=list
for i in range(9):
entry=entry.copy()
shuffle(entry )
print(entry )
matr.append(entry)
print(matr)
You're looking to produce a random (valid) sudoku board. This is not trivial and a trial/error approach with random numbers will take forever to produce a valid result. Here's a sudoku generator that will do it using dynamic programming:
import random
groups = [ p//27*3+p%9//3 for p in range(81) ]
colNums = [ set(range(1,10)) for _ in range(9) ]
rowNums = [ set(range(1,10)) for _ in range(9) ]
grpNums = [ set(range(1,10)) for _ in range(9) ]
sudoku = [ [0]*9 for _ in range(9) ]
pos = 0
tried = [ set() for _ in range(81)]
while pos < 81:
row,col,group = pos//9,pos%9,groups[pos]
previousNumber = sudoku[row][col]
if previousNumber != 0: # make backtracked number available again
sudoku[row][col] = 0
colNums[col].add(previousNumber)
rowNums[row].add(previousNumber)
grpNums[group].add(previousNumber)
available = colNums[col] & rowNums[row] & grpNums[group]
available -= tried[pos]
if available: # select an available number at random
number = random.choice(list(available))
sudoku[row][col] = number
colNums[col].discard(number)
rowNums[row].discard(number)
grpNums[group].discard(number)
tried[pos].add(number)
pos += 1
else:
tried[pos] = set() # no available number, backtrack to previous position
pos -= 1
for line in sudoku:
print(line)
The algorithm attempts to place a number at each of the 81 positions sequentially. If there is a conflict it will try the next available number for that position. If there are no numbers that will fit at that position, then it backtracks to the previous position and tries the next available number there. It will move back and forth through the 81 positions until it manages to place a valid number at the last position.
In order to quickly check if a number is valid at a given position, the algorithm maintains 3 lists of sets. One for the rows, one for the columns and one for the nine 3x3 blocks. These sets contain the unused numbers for a given row, column or block. Each time a number is placed on the board, it is removed from the corresponding row/column/block sets. This makes it unavailable for all subsequent positions that are on the same row, column or block.
When the algorithm needs to backtrack, it returns the number at the previous position to its 3 availability sets. The position to which the algorithm is backtracking will move on to another number so the previously attempted number must become available for subsequent positions.
The positions are numbered from 0 to 80 to facilitate tracking and comparisons in sets. These position numbers can easily be converted to row and column using simple division and modulo operators. The conversion to group numbers is a little bit more complicates but it is also just a matter of division and modulo.
Variables used:
groups: conversion from a position number to a group number
colNums: sets of available positions for the 9 columns
rowNums: sets of available positions for the 9 rows
grpNums: sets of available positions for the 9 groups (3x3 blocks)
sudoku: the final board (9 rows of 9 numbers)
pos: current position where an attempt to place a number is being made
tried: set of numbers that have already been tried at each position so far. When backtracking the current set is cleared because the availability of positions will be different once the previous position is changed.
row,col,group are indexes corresponding to the current position (pos)
If you don't want the 3x3 blocks restriction, you can easily remove it by deleting the parts of the code that use/assign the group, groups and grpNums variables.
In that case, there is a much simpler (and faster) technique to produce a random matrix that meets the row/column unicity constraint:
import random
numbers = random.sample(range(1,10),9)
cols = random.sample(range(9),9)
rows = random.sample(range(9),9)
square = [[numbers[(r+c)%9] for c in cols] for r in rows]
for line in square: print(line)
[8, 9, 1, 7, 6, 4, 5, 3, 2]
[5, 2, 9, 6, 4, 3, 1, 8, 7]
[2, 4, 6, 8, 5, 1, 7, 9, 3]
[1, 7, 2, 4, 3, 8, 9, 5, 6]
[7, 3, 4, 5, 1, 9, 6, 2, 8]
[3, 1, 5, 2, 7, 6, 8, 4, 9]
[4, 5, 8, 9, 2, 7, 3, 6, 1]
[9, 6, 7, 3, 8, 5, 2, 1, 4]
[6, 8, 3, 1, 9, 2, 4, 7, 5]
Note that this may not produces all of the valid random matrices
To explain this one, it is best to start with a simple matrix of sequential indexes where each row is offset by one more than the preceding row:
matrix = [ [(r+c)%9 for c in range(9)] for r in range(9) ]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 0]
[2, 3, 4, 5, 6, 7, 8, 0, 1]
[3, 4, 5, 6, 7, 8, 0, 1, 2]
[4, 5, 6, 7, 8, 0, 1, 2, 3]
[5, 6, 7, 8, 0, 1, 2, 3, 4]
[6, 7, 8, 0, 1, 2, 3, 4, 5]
[7, 8, 0, 1, 2, 3, 4, 5, 6]
[8, 0, 1, 2, 3, 4, 5, 6, 7]
As you can see each row has indexes 0 to 8 (so no repetitions) and each column also has indexes 0 to 8 with no repetition because of offsetting.
Now if we create a list of numbers from 1 to 9 and shuffle it, we can replace the indexes in the matrix by the corresponding number in the shuffled list. Since each index maps to a different number, the resulting matrix will not have any repetitions on lines or columns.
numbers = random.sample(range(1,10),9) # [1, 5, 9, 8, 3, 7, 6, 2, 4]
matrix = [ [numbers[i] for i in row] for row in matrix ]
[1, 5, 9, 8, 3, 7, 6, 2, 4]
[5, 9, 8, 3, 7, 6, 2, 4, 1]
[9, 8, 3, 7, 6, 2, 4, 1, 5]
[8, 3, 7, 6, 2, 4, 1, 5, 9]
[3, 7, 6, 2, 4, 1, 5, 9, 8]
[7, 6, 2, 4, 1, 5, 9, 8, 3]
[6, 2, 4, 1, 5, 9, 8, 3, 7]
[2, 4, 1, 5, 9, 8, 3, 7, 6]
[4, 1, 5, 9, 8, 3, 7, 6, 2]
Finally we can shuffle the rows to get a more random organization of the matrix
random.shuffle(matrix)
[5, 9, 8, 3, 7, 6, 2, 4, 1]
[9, 8, 3, 7, 6, 2, 4, 1, 5]
[1, 5, 9, 8, 3, 7, 6, 2, 4]
[7, 6, 2, 4, 1, 5, 9, 8, 3]
[2, 4, 1, 5, 9, 8, 3, 7, 6]
[6, 2, 4, 1, 5, 9, 8, 3, 7]
[4, 1, 5, 9, 8, 3, 7, 6, 2]
[8, 3, 7, 6, 2, 4, 1, 5, 9]
[3, 7, 6, 2, 4, 1, 5, 9, 8]
and columns:
cols = random.sample(range(9),9) # [7, 4, 3, 0, 8, 1, 2, 5, 6]
matrix = [[matrix[r][c] for c in cols] for r in range(9)]
[4, 7, 3, 5, 1, 9, 8, 6, 2]
[1, 6, 7, 9, 5, 8, 3, 2, 4]
[2, 3, 8, 1, 4, 5, 9, 7, 6]
[8, 1, 4, 7, 3, 6, 2, 5, 9]
[7, 9, 5, 2, 6, 4, 1, 8, 3]
[3, 5, 1, 6, 7, 2, 4, 9, 8]
[6, 8, 9, 4, 2, 1, 5, 3, 7]
[5, 2, 6, 8, 9, 3, 7, 4, 1]
[9, 4, 2, 3, 8, 7, 6, 1, 5]
The solution (above) combines these steps into a single list comprehension but uses exactly the same approach.
Using the same approach, it is also possible to produce a random sudoku board (with the 3x3 block constraint). The formula for the offsets is a bit more complex and the shuffling of rows and columns can only be done within and between block groups.
from random import sample
base = 3 # Will generate any size of random sudoku board instantly
side = base*base
nums = sample(range(1,side+1),side) # random numbers
board = [[nums[(base*(r%base)+r//base+c)%side] for c in range(side) ] for r in range(side)]
rowGr = sample(range(base),base) # random rows/horizontal blocks
rows = [ r for g in rowGr for r in sample(range(g*base,(g+1)*base),base) ]
colGr = sample(range(base),base) # random column/vertical blocks
cols = [ c for g in colGr for c in sample(range(g*base,(g+1)*base),base) ]
board = [[board[r][c] for c in cols] for r in rows]
for line in board:print(line)
[7, 5, 3, 6, 9, 4, 1, 2, 8]
[6, 9, 4, 1, 2, 8, 7, 5, 3]
[1, 2, 8, 7, 5, 3, 6, 9, 4]
[2, 8, 7, 5, 3, 6, 9, 4, 1]
[5, 3, 6, 9, 4, 1, 2, 8, 7]
[9, 4, 1, 2, 8, 7, 5, 3, 6]
[8, 7, 5, 3, 6, 9, 4, 1, 2]
[3, 6, 9, 4, 1, 2, 8, 7, 5]
[4, 1, 2, 8, 7, 5, 3, 6, 9]
Steps
Generate a shuffled list
Left rotated by 1 to generate the matrix
Shuffle rows in matrix
Shuffle cols in matrix (optional)
from random import shuffle
a = list(range(10))
shuffle(a)
# Use slicing to left rotate
m = [a[i:] + a[:i] for i in range(10)]
# Shuffle rows in matrix
shuffle(m)
# Shuffle cols in matrix (optional)
m = list(map(list, zip(*m))) # Transpose the matrix
shuffle(m)
print('\n'.join(map(str, m)))
If you just need 1 matrix and no variation is expected, then you can keep shifting array to either right or left. Here is an example:
def cyclic_rotate(input):
return [input[-1]] + input[0:-1]
if __name__ == "__main__":
result = []
input = [i for i in range(9)]
prev = input
for i in range(9):
shifted_arr = cyclic_rotate(prev)
result.append(shifted_arr)
prev = shifted_arr
# Does only pretty print of 2-D matrix
print('\n'.join(['\t'.join([str(cell) for cell in row]) for row in result]))
Try this and you will get what you want:
>>> matrix = []
>>> for i in range(1,10):
... temp = []
... for j in range(i,i+9):
... if j >= 10:
... temp.append(int(j%10)+1)
... else:
... temp.append(j)
... matrix.append(temp)
...
>>> matrix
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9, 1], [3, 4, 5, 6, 7, 8, 9, 1, 2], [4, 5, 6, 7, 8, 9, 1, 2, 3], [5, 6, 7, 8, 9, 1, 2, 3, 4], [6, 7, 8, 9, 1, 2, 3, 4, 5], [7, 8, 9, 1, 2, 3, 4, 5, 6], [8, 9, 1, 2, 3, 4, 5, 6, 7], [9, 1, 2, 3, 4, 5, 6, 7, 8]]
Hope this helps you.

The Insertion Sort algorithm. What's happening step by step?

I'm a new data science student and I am trying to understand what exactly is happening inside the insertion sort algorithm.
Can anyone tell me what's happening step by step? It would be most appreciated.
Below is a code I wrote with some verbose so I could hopefully understand what was happening a little better but to no avail.
A = [4, 1, 7, 52, 10, 12]
B = [4, 1, 7, 52, 10, 12]
def InsertionSort(A):
for j in range(1, len(A)):
print("***************** LOOP", j, "*********************\n")
key = A[j]
i = j - 1
print("i:", i, " | A[i]:", A[i], " | key:", key, "\n")
print("IS i:", i, ">= 0 and", A[i], ">", key, "?", "\n")
while i >= 0 and A[i] > key:
print("TRUE:", i, ">= 0 and", A[i], ">", key, "\n")
A[i + 1] = A[i] # left cell switches places with right cell
i = i - 1
A[i + 1] = key
print("\n\n")
print("=================== END =====================")
InsertionSort(A)
print("A (not-sorted): ", B)
print("A (sorted): ", A)
I don't understand how it switches the numbers.
Insertion sort works by looking at each element in the array and moving it towards the beginning of the array until it's smaller than everything seen so far.
To do this, an outer loop considers each element in the array (skip element 0 because there's nothing to compare it with and you don't want to IndexError). The inner loop slides the element starting at the current i index leftward, comparing it against each previous element j-1 in the array until the section of the array seen so far is sorted.
Your debug output relies too heavily on text and numbers rather than a visual of the array, which is all that's needed to see the algorithm in action. I also recommend using a slightly larger array size.
As an aside, I recommend sticking to Python camel_case naming convention.
If you play with this code and walk through the output step by step and I think you'll see what's going on:
a = [7, 3, 6, 9, 4, 5, 8, 0, 1, 2]
def insertion_sort(a):
for i in range(1, len(a)):
j = i
print("moving %d:" % a[j])
while j > 0 and a[j-1] > a[j]:
a[j-1], a[j] = a[j], a[j-1]
j -= 1
print(a)
print(" " + " " * j + "^---")
print()
print("original: \n" + str(a) + "\n")
insertion_sort(a)
Output:
original:
[7, 3, 6, 9, 4, 5, 8, 0, 1, 2]
moving 3:
[3, 7, 6, 9, 4, 5, 8, 0, 1, 2]
^---
moving 6:
[3, 6, 7, 9, 4, 5, 8, 0, 1, 2]
^---
moving 9:
moving 4:
[3, 6, 7, 4, 9, 5, 8, 0, 1, 2]
^---
[3, 6, 4, 7, 9, 5, 8, 0, 1, 2]
^---
[3, 4, 6, 7, 9, 5, 8, 0, 1, 2]
^---
moving 5:
[3, 4, 6, 7, 5, 9, 8, 0, 1, 2]
^---
[3, 4, 6, 5, 7, 9, 8, 0, 1, 2]
^---
[3, 4, 5, 6, 7, 9, 8, 0, 1, 2]
^---
moving 8:
[3, 4, 5, 6, 7, 8, 9, 0, 1, 2]
^---
moving 0:
[3, 4, 5, 6, 7, 8, 0, 9, 1, 2]
^---
[3, 4, 5, 6, 7, 0, 8, 9, 1, 2]
^---
[3, 4, 5, 6, 0, 7, 8, 9, 1, 2]
^---
[3, 4, 5, 0, 6, 7, 8, 9, 1, 2]
^---
[3, 4, 0, 5, 6, 7, 8, 9, 1, 2]
^---
[3, 0, 4, 5, 6, 7, 8, 9, 1, 2]
^---
[0, 3, 4, 5, 6, 7, 8, 9, 1, 2]
^---
moving 1:
[0, 3, 4, 5, 6, 7, 8, 1, 9, 2]
^---
[0, 3, 4, 5, 6, 7, 1, 8, 9, 2]
^---
[0, 3, 4, 5, 6, 1, 7, 8, 9, 2]
^---
[0, 3, 4, 5, 1, 6, 7, 8, 9, 2]
^---
[0, 3, 4, 1, 5, 6, 7, 8, 9, 2]
^---
[0, 3, 1, 4, 5, 6, 7, 8, 9, 2]
^---
[0, 1, 3, 4, 5, 6, 7, 8, 9, 2]
^---
moving 2:
[0, 1, 3, 4, 5, 6, 7, 8, 2, 9]
^---
[0, 1, 3, 4, 5, 6, 7, 2, 8, 9]
^---
[0, 1, 3, 4, 5, 6, 2, 7, 8, 9]
^---
[0, 1, 3, 4, 5, 2, 6, 7, 8, 9]
^---
[0, 1, 3, 4, 2, 5, 6, 7, 8, 9]
^---
[0, 1, 3, 2, 4, 5, 6, 7, 8, 9]
^---
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
^---
Unlike bubble sort, Insertion sort does not merely swap numbers (conceptually).
First, it stores the value at current index j in a variable key.
Then it starts at just previous index i of current index (i = j - 1), and traverses backwards (i = i - 1) towards the beginning. For each index, it compares value with key (while i >= 0 and A[i] > key). If value at i is more than key, it shifts the value one index forward (A[i + 1] = A[i]), until it finds a value equal or lower than key. When such value is found, key should come just after that in sorted array, so it places key at next index i+1 (A[i + 1] = key). It repeats the same process for all elements and result is sorted array.
This will help more https://visualgo.net/bn/sorting?slide=8.
The function is ordering a given array. First it iterates over the elements of the array, starting from the second element:
for j in range(1, len(A)):
Then it compares element j (key) with element j-1 (A[i]):
while i >= 0 and A[i] > key:
In case element j-1 is bigger than element j it needs to swap them, so it does the swap:
A[i + 1] = A[i]
Now it needs to check if this is true also for element j-2, hence the while loop. Hope this helps a bit.

Python append values to empty list by skipping values in between a list

Just a minimal example of what I want to achieve.
I have an array:
array = [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,....,1,2,3,4,5,6,7,8,9,10]
I would like to loop through this array and create a new array which looks like this:
new_array = [1,1,2,1,2,3,1,2,3,4,1,2,3,4,5,....,1,2,3,4,5,6,7,8,9,10]
i.e. loop through array a, get the first value (i.e. 1), then skip the remaining 9 values, then get the first and the second value (i.e. 1,2), then skip the remaining 8 values, and so on.
The idea I came up with was to create indices and use it in the following way:
In [1]: indices = np.arange(1,10,1)
Out[1]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
new_array = []
for i in array:
for a,b in zip(indices,range(10)):
new_array.append(i[0:a]) # here I am including i[0:1], i[0:2] and so on
So it loops through array and gets the first value, then skips the remaining 9 values, then gets the first two values and skips the remaining 8 values and so on.
But this doesn't seem to work. How can I achieve this ?
If you don't need all values (only pass your scheme)
list = [1,2,3,4,5,6,7,8,9,10] * 10
output = []
skip = 9
i = 0
while skip > 0:
output.append(list[i])
i += skip + 1
skip -= 1
print(list)
print(output)
But your "new_array" doesn't pass your algorithm. Why not:
[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10]
If I get first 1 (it has index 0) after skip 9 values I will get 1, after then skipping 8 values I won't get 2
Edit: Ok, I understand now. This should work:
list = [1,2,3,4,5,6,7,8,9,10] * 10
output = []
skip = 9
i = 0
j = 0
add = 1
while skip >= 0:
newList = list[i:j+1]
for x in newList:
output.append(x)
i += skip + add
j += skip + add + 1
add += 1
skip -= 1
print(output)
For a signle list you can also use list extension for this:
list = [1,2,3,4,5,6,7,8,9,10]
output = []
i = 1
while i <= 10:
output.extend(list[0:i])
i +=1
print output
For your list you can extend this to:
list = [1,2,3,4,5,6,7,8,9,10]*10
output = []
i = 1
j = 0
k = 1
while k <= 10:
output.extend(list[j:i])
j +=10
k +=1
i = j+k
print output
can you please try this code. I have tested this code on python 3 and it is working fine.
inp = [1,2,3,4,5,6,7,8,9,10] * 10
inp_len = len(inp);
output = [inp[0]]
skip = 9
limit= skip +2;
pointer = 1;
while skip > 0:
pointer = pointer+skip;
if(pointer >inp_len):
pointer = pointer %inp_len;
for x in inp[pointer : pointer+limit-skip ]:
output.append(x);
pointer= pointer+ limit-skip ;
skip=skip-1;
print(inp)
print(output)
Explaination - Adding default first element and then adding elements in below order.
skip 9 elements = [1, 2]
skip 8 elements = [1, 2, 3]
skip 7 elements = [1, 2, 3, 4]
skip 6 elements = [1, 2, 3, 4, 5]
skip 5 elements = [1, 2, 3, 4, 5, 6]
skip 4 elements = [1, 2, 3, 4, 5, 6, 7]
skip 3 elements = [1, 2, 3, 4, 5, 6, 7, 8]
skip 2 elements = [1, 2, 3, 4, 5, 6, 7, 8, 9]
skip 1 elements = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Please test it with your input . Here i am using a defined list.
Input list -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Output list - [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
How about:
list = [1,2,3,4,5,6,7,8,9,10] * 10;
output = [];
take = 1;
index = 0;
while index < len(list):
# take the "take" next elements, notice the "index" is not changing.
for i in range(take):
output.append(list[index + i]);
# Skip the remaining values and increase the "take"
index += 10;
take += 1;
print(list)
print(output)
You can also go like this with two indices:
list = [1,2,3,4,5,6,7,8,9,10] * 10;
output = [];
index = 0;
for i in range(10):
for j in range(10):
if j <= i:
output.append(list[index + i]);
index++;
print(list)
print(output)
array = [1,2,3,4,5,6,7,8,9,10]*10
new_array = []
c=j=0
while c < len(array):
for i in range(0,j):
new_array.append(array[i])
i+=1
j+=1
c+=10
print(new_array)
Output
[1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9]
it's not too different from printing a triangle with numbers from 1 to 10.
array = [x for x in range(1,11)]*10 #here 10 means adding same list 10 times
new_array = []
for i in range(10):
new_array += array[10*i:10*i+i+1]
print(new_array)
hope this helps!
It takes 0.0005 sec

Efficiency between two sorting functions

I have created a two functions which sorts integers from lowest value to highest then back to low. Does this type of sort exist? Anyways, I have the following two sorting functions which I have created which produce the same output. I was wondering which is the most efficient of the two? Are there any improvements I can make to either?
sortMiddleMax1
Create a new reverse sorted list of original
Start from index 1 to length of list step by 2
sortMiddleMax2
Sorts the list in-place
Start from last index to 0 step by 2
I tried to make the second more efficient than the first. I did not create a new list in memory and I appended to the end instead of pushing the whole list right. Am I correct in this assumption?
Functions
def sortMiddleMax1(aList=None, verbose=False):
if aList == None or len(aList) < 2:
return aList
else:
sList = sorted(x, key=None, reverse=True)
if verbose: print sList
index = 1
while index < len(sList):
tmp = sList[index]
del sList[index]
sList.insert(0, tmp)
index+=2
if verbose: print sList
return sList
def sortMiddleMax2(aList=None, verbose=False):
if aList == None or len(aList) < 2:
return aList
else:
aList.sort()
if verbose: print aList
index = len(aList)-1
while index > 0:
tmp = aList[index]
del aList[index]
aList.append(tmp)
index-=2
if verbose: print aList
return aList
Main
x = [1,4,6,8,3,5,7,1,5,8,3,9,2,8]
print '############# sortMiddleMax1 #############'
x1 = sortMiddleMax1(x, True)
print '############# sortMiddleMax2 #############'
x2 = sortMiddleMax2(x, True)
Output
############# sortMiddleMax1 #############
[9, 8, 8, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[8, 9, 8, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[8, 8, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[6, 8, 8, 9, 8, 7, 5, 5, 4, 3, 3, 2, 1, 1]
[5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 3, 2, 1, 1]
[3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 2, 1, 1]
[2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1, 1]
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]
############# sortMiddleMax2 #############
[1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9]
[1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9]
[1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 9, 8]
[1, 1, 2, 3, 3, 4, 5, 5, 6, 8, 8, 9, 8, 7]
[1, 1, 2, 3, 3, 4, 5, 6, 8, 8, 9, 8, 7, 5]
[1, 1, 2, 3, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4]
[1, 1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3]
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]
You can use Python's extended slicing. [::2] means take every second element. [::-2] means take every second element from the end and work backwards. Here the first slice starts at 0 for even length list and 1 for odd length lists
>>> x = [1, 4, 6, 8, 3, 5, 7, 1, 5, 8, 3, 9, 2, 8]
>>> x = sorted(x)
>>> x[len(x)%2::2] + x[::-2]
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]
You can use list slice to get the result without for loop:
x = sorted([1,4,6,8,3,5,7,1,5,8,3,9,2,8])
x2 = x[::2] + x[1::2][::-1]
I suspect your two current versions perform exactly the same. However, they both can be improved by using slices to get at the values in the list, rather than by deleting and inserting values.
Each del and each insert is O(N) and you're doing N/2 of each, so the sort will be O(N^2). Slicing is O(N) as well, but only needs to be done twice. The time taken for the sort O(N log N) will dominate, asymptotically.
def sortMiddle3(aList):
s = sorted(aList) # sort the provided list
# now take the even indexed items, followed by the odd indexes in reverse
if len(s) % 2 == 0: # is the number of items even?
return s[::2] + s[-1::-2] # if so, the last item has an odd index
else:
return s[::2] + s[-2::-2]
Example output:
>>> x = [1,4,6,8,3,5,7,1,5,8,3,9,2,8]
>>> sortMiddle3(x)
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]

Categories

Resources