Python - Append Help - String & list - python

Another append question... This is my code:
def s(xs,n,m):
t = []
while n < m:
n += 2
t.append(xs[n])
return t
When I evaluate the following:
x = s('African', 0, 3)
Why does it return this?:
['r', 'c']

while n < m:
n += 2 # at this point n = 2 because you've passed 0
t.append(xs[n]) # you append r to t since xs[2] = r
but n < m still, so next iteration:
while n < m:
n += 2 # at this point n = 4
t.append(xs[n]) # you append c to t since xs[4] = c
now n > m, so the function returns ['r', 'c']. Everything is correct.

Ok, so line-by-line...
Your call looks like this:
x = s('African', 0, 3)
so what happens is:
Step 1. - initial assignement
def s(xs,n,m):
xs='African', n=0 and m=3 and then:
t = []
(so, empty list t is introduced).
Step 2. - loop
Then the following condition is evaluated:
while n < m:
to True, because 0 < 3.
And then n is increased:
n += 2
so it is now equal to 2.
Then the appropriate element is appended to the empty t list:
t.append(xs[n])
and this element is "r", because xs[2] == 'r'.
Then n < m condition is again evaluated to True (because 2 < 3), so the loop executes again:
n += 2
and n is now equal to 4.
Then appropriate char from xs string is appended to t list (which already has one element, r, as we mentioned above).
t.append(xs[n])
and this element is "c" (because xs[4] is exactly "c").
Then condition for while loop is again evaluated, but this time to False (because 4 < 3 is not true), so the loop stops executing...
(Step 3. - after the loop) ...and the program flow goes to the final statement of the function, which is:
return t
And t returns the list we filled with two elements - as a result, the function returns list ['r', 'c'].
Is it clear enough? Did it help?

Related

Remove triplets of adjacent numbers from the list [duplicate]

This question already has answers here:
Write a function lines(a) that determines how many balls will be destroyed
(6 answers)
Closed 2 years ago.
Here is the problem. The input is a list of integers. If three adjacent numbers appear next to each other they should be dropped and the operation goes again. Iphone app with the balls of the same colors. The output should be the count of the balls that will be destroyed.
Example:
input = [3,3,4,4,4,3,4]
1st iteration
output: [3,3,3,4]
Final output:
6
4,4,4 on the first iteration, so three balls. and 3,3,3 on the second. Overall six.
My code is below. It will remove the 4,4,4 but will fail after, because list index will quickly go out of range.
def balls(a):
curr_index = 0
removed_count = 0
while len(a) > 2:
if (a[curr_index] == a[curr_index+1]) and (a[curr_index] == a[curr_index+2]):
a.remove(a[curr_index])
a.remove(a[curr_index+1])
a.remove(a[curr_index+2])
curr_index += 1
removed_count += 3
return removed_count
a = [3, 3, 4, 4, 4, 3, 4]
print(balls(a)) # should print 6
Any ideas?
input_values = [3,3,4,4,4,3,4]
values = input_values
while len(values) >= 3:
for x in range(0,len(values)-2):
# if we find 3 values in ar row
if values[x] == values[x+1] and values[x] == values[x+2]:
# update values by cutting out the series
values = values[:x] + values[x+3:]
# break this for loop
break
else:
# for loops can have an else statement
# this means that we came at the end of the for loop
# this if we didn't break the loop (and didn't found a valid triple)
# then we brea
break
#result - amount of removed balls
values, len(input_values) - len(values)
A more generic approach where you can define N
(it will find exact N values)
input_values = [3,3,4,4,4,4,3,3,4]
# amount of neighbours
N = 4
values = input_values
# keep looping as long as we've N values
while len(values) >= N:
# we need this if we break the inner loop
stop = False
# loop over values from left to right
# 3 -> 3 -> 4 -> 4 -> ... until -N + 1
# because that is the last spot that we've N values left
for x in range(0, len(values) - N + 1):
# scout for the next numbers (x+1 x+2 x+3 ....)
# this goes from, x+1 until the end of the serie
# also start counting from 2 - because
# if we've a single match, 2 numbers are equal
for e, y in enumerate(range(x+1, len(values)), start=2):
# if x and y are different, the stop this scouting
# remember y = x+1 x+2 x+3 ....
if values[x] != values[y]:
break
# if we reached this stage, we know that
# x and x+1 x+2 ... are equal
# but also check if we've enough matches
if e == N:
# update values by cutting out the series
values = values[:x] + values[y+1:]
stop = True
break
if stop:
break
else:
# for loops can have an else statement
# this means that we came at the end of the for loop
# this if we didn't break the loop (and didn't found a valid triple)
# then we brea
break
values, len(input_values) - len(values)
Here is one way to do it:
your_list=[3, 3, 4, 4, 4, 3, 4]
def remove_one(l):
if len(l)>2:
for i in range(len(l)-2):
if l[i]==l[i+1]==l[i+2]:
res.extend(l[i:i+3])
l=l[:i]+l[i+3:]
return l
return []
res=[]
while len(your_list)>2:
your_list=remove_one(your_list)
print(len(res))
Output:
6
An approach with a minimal threshold
input_values = [3,3,4,4,4,4,4,3,3,4]
# threshold
N = 3
values = input_values
while len(values) >= N:
# we need this if we break the inner loop
stop = False
# loop over values
for x in range(0, len(values) - N + 1):
# scout for the next numbers (x+1 x+2 x+3 ....)
for e, y in enumerate(range(x+1, len(values)), start=2):
# check if the values of x and x+1 (x+2 x+3 ...) are different
if values[x] != values[y]:
# if so, check if we've reached our threshold of N
if e >= N:
# if this is the case update values by cutting out the series
values = values[:x] + values[y:]
stop = True
break
# if x+n != x then we break this scouting loop
break
# stop is True, this means, that we found N neibouring numbers
# thus we can break this loop, and start over with a new* value
if stop:
break
else:
# for loops can have an else statement
# this means that we came at the end of the for loop
# thus if we didn't break the loop (and didn't found a valid triple)
# then we break
break
values, len(input_values) - len(values)
There are a couple of issues with your code.
The first is you're trying to iterate over the list a single time, but that won't work for your example.
The second is you're assuming the list will always reduce to less than 3, which won't be the case if you have more numbers.
There are also some places you can simplify the syntax, for example:
if (a[curr_index] == a[curr_index+1]) and (a[curr_index] == a[curr_index+2]):
is equivalent to:
if a[curr_index] == a[curr_index + 1] == a[curr_index + 2]:
And
a.remove(a[curr_index])
a.remove(a[curr_index+1])
a.remove(a[curr_index+2])
is equivalent to:
del a[curr_index: curr_index + 3]
So here is one way to accomplish this, thought there are more efficient ways.
def balls(a):
removed = 0
complete = False
# Run until complete is set or the list is too short for a match
while not complete and len(a) >= 3:
for idx, val in enumerate(a):
if val == a[idx + 1] == a[idx + 2]:
del a[idx: idx + 3]
removed += 3
break # Restart every time we find a match
# If it's the last possible match, set complete
if idx == len(a) - 3:
complete = True
break
return removed
I'm little bit late, but my idea is to do the processing in one pass. The idea is that when you drop a tripple, go back two positions to re-check if a new tripple has been created by that change.
Example:
3 3 4 4 4 3
^--- tripple found here, remove it
3 3 3
^--- move the cursor 2 positions left and continue checking
The code:
def drop3(lst):
# drop3 destroys the lst, make a copy if you want to keep it
dropped = 0
cursor = 0
limit = len(lst) - 2
while cursor < limit:
if lst[cursor] == lst[cursor+1] == lst[cursor+2]:
del lst[cursor:cursor+3]
cursor = max(0, cursor-2)
limit -= 3
dropped += 3
else:
cursor += 1
return dropped
A linear-tme solution:
def balls(a):
b = []
for x in a:
b.append(x)
if b[-3:] == [x] * 3:
del b[-3:]
return len(a) - len(b)

Heap's Algorithm - Non Recursive Method in Python to generate permutations

I am a newbie to programming. I am working on Heap's Algorithm, specifically non-recursive method. There is not so much explanation available on internet, to how the algorithm works. I found this piece of work from Bernardo Sulzbach but he doesn't explain how his algorithm works. I am stuck on it from days, tried everything couldn't figure it out. I have added comments after each line to make myself understand -- what's happening here? but I still couldn't make it work. Am I doing something wrong? Please help.
# Heap's Algorithm (Non Recursive)
# function to swap values in python
def swap(elements, i, j):
elements[i], elements[j] = elements[j], elements[i]
# function to generate permutation
def generate_permutations(elements, n):
# Passing two parameters of elements and n to function "generate_permutations".
c = [0] * n
# c is a new list and its value set to an array literal with value 0, n times.
# Example - [a] * 3 ==> ['a', 'a', 'a', 'a']
yield elements
# "yield" statement is used to define generators, while "return" statement causes a function to exit.
# "yield" replacing the return of a function to provide a result to its caller without destroying
# local variables. Unlike a function, where on each call it starts with new sets of variables, a generator
# will resume the execution where it left off.
i = 0
# i is a new variable and its value is set to 0. It can also be used to count the number of loop runs.
while i < n:
# while loop ==> while i is less than n, do following:
if c[i] < i:
# if statement ==> while i is less than n and if any element from 'c' list is less than i,
# then do following:
if i % 2 == 0:
# if statement ==> while i is less than n, and if any element in 'c' list is less than i, and
# i is an even number, then do following:
swap(elements, 0, i)
# calling swap function and passing following arguments: elements, '0' and 'i'
else:
# else, if all three conditions above are not true then do following:
swap(elements, c[i], i)
# calling swap funtions and passing following arguments: elements, an item from 'c' list and 'i'
yield elements
# ??? yield elements
c[i] += 1
# after that, increment c[i] by 1.
i = 0
# set the value of i to 0
else:
# else, if c[i] < i is not true the do the following.
c[i] = 0
# set the value of c[i] to 0
i += 1
# and increment i by 1
def permutations(elements):
return generate_permutations(elements, len(elements))
# Driver Code
# c = ?
# n = ?
# i = ?
print(permutations(['abc']))
Just cleaning up your code (too many comments):
# Heap's Algorithm (Non Recursive)
# https://en.wikipedia.org/wiki/Heap%27s_algorithm
def swap(seq, i, j):
seq[i], seq[j] = seq[j], seq[i]
def generate_permutations(seq, seqLen, resLen):
c = [0] * seqLen
yield seq[:resLen]
i = 0
while i < seqLen:
if c[i] < i:
if i % 2 == 0:
swap(seq, 0, i)
else:
swap(seq, c[i], i)
yield seq[:resLen]
c[i] += 1
i = 0
else:
c[i] = 0
i += 1
def permutations(seq, resLen=None):
if not resLen: resLen = len(seq)
return generate_permutations(seq, len(seq), resLen)
for p in permutations([1,2,3]): print(p)
for p in permutations([1,2,3],2): print(p)

increment numbers in list comprehension

I am new to python. I am learning list comprehension to shorten my code to minimum. But I am unable to incremnent inside a list comprehension. Like this code:
n = 0; c = 0
for i in range(input()):
m = map(int,raw_input().split())
[n+=1 if m[0] > m[1] else c+=1]
print ['N', 'C'][c > n]
My input:
3
3 4
2 4
2 5
The output should be:
N
List comprehensions are for making lists. You appear to want
if m[0] > m[1]: n+=1
else: c+=1
This does not address the other errors in the code.
You do not actually need to keep track of both n and c, since you can calculate one from the other and the total (your first input).
t = input()
n = 0
for i in range(t):
a, b = map(int, raw_input().split())
n += (a > b)
print 'N' if n >= t/2 else 'C'
If you really want to make this shorter (note: except for Code Golf, shorter does not always mean better) you could try something like this:
t = input()
n = sum(1 for i in range(t) for a, b in [map(int, raw_input().split())] if a > b)
print 'N' if n >= t/2 else 'C'
Or without t, use cmp (retired in Python 3) to count +1 for a > b and -1 for a < b, then compare to 0. But this will handle the case a == b differently, and the readability finally goes down the drain.
n = sum(cmp(*map(int, raw_input().split())) for _ in range(input()))
print 'N' if n >= 0 else 'C'
The above code has multiple problems -
We are not converting the input() to int
We are using both input() and raw_input()
List comprehension does not allow += operator

Similarity Measure in Python

I am working on this coding challenge named Similarity Measure. Now the problem is my code works fine for some test cases, and failed due to the Time Limit Exceed problem. However, my code is not wrong, takes more than 25 sec for input of range 10^4.
I need to know what I can do to make it more efficient, I cannot think on any better solution than my code.
Question goes like this:
Problems states that given an array of positive integers, and now we have to answer based upon the Q queries.
Query: Given two indices L,R, determine the maximum absolute difference of index of two same elements lies between L and R
If in a range, there are no two same inputs then return 0
INPUT FORMAT
The first line contains N, no. of elements in the array A
The Second line contains N space separated integers that are elements of the array A
The third line contains Q the number of queries
Each of the Q lines contains L, R
CONSTRAINTS
1 <= N, Q <= 10^4
1 <= Ai <= 10^4
1 <= L, R <= N
OUTPUT FORMAT
For each query, print the ans in a new line
Sample Input
5
1 1 2 1 2
5
2 3
3 4
2 4
3 5
1 5
Sample Output
0
0
2
2
3
Explanation
[2,3] - No two elements are same
[3,4] - No two elements are same
[2,4] - there are two 1's so ans = |4-2| = 2
[3,5] - there are two 2's so ans = |5-3| = 2
[1,5] - there are three 1's and two 2's so ans = max(|4-2|, |5-3|, |4-1|, |2-1|) = 3
Here is my algorithm:
To take the input and test the range in a different method
Input will be L, R and the Array
For difference between L and R equal to 1, check if the next element is equal, return 1 else return 0
For difference more than 1, loop through array
Make a nested loop to check for the same element, if yes, store the difference into maxVal variable
Return maxVal
My Code:
def ansArray(L, R, arr):
maxVal = 0
if abs(R - L) == 1:
if arr[L-1] == arr[R-1]: return 1
else: return 0
else:
for i in range(L-1, R):
for j in range(i+1, R):
if arr[i] == arr[j]:
if (j-i) > maxVal: maxVal = j-i
return maxVal
if __name__ == '__main__':
input()
arr = (input().split())
for i in range(int(input())):
L, R = input().split()
print(ansArray(int(L), int(R), arr))
Please help me with this. I really want to learn a different and a more efficient way to solve this problem. Need to pass all the TEST CASES. :)
You can try this code:
import collections
def ansArray(L, R, arr):
dct = collections.defaultdict(list)
for index in range(L - 1, R):
dct[arr[index]].append(index)
return max(lst[-1] - lst[0] for lst in dct.values())
if __name__ == '__main__':
input()
arr = (input().split())
for i in range(int(input())):
L, R = input().split()
print(ansArray(int(L), int(R), arr))
Explanation:
dct is a dictionary that for every seen number keeps a list of indices. The list is sorted so lst[-1] - lst[0] will give maximum absolute difference for this number. Applying max to all this differences you get the answer. Code complexity is O(R - L).
This can be solved as O(N) approximately the following way:
from collections import defaultdict
def ansArray(L, R, arr) :
# collect the positions and save them into the dictionary
positions = defaultdict(list)
for i,j in enumerate(arr[L:R+1]) :
positions[j].append(i)
# create the list of the max differences in index
max_diff = list()
for vals in positions.values() :
max_diff.append( max(vals) - min(vals) )
# now return the max element from the list we have just created
if len(max_diff) :
return max(max_diff)
else :
return 0

Competition practise task (Python)

Not sure if it's the best title. The explanation of what the program is suposed to do is below, my version only works with the first example but it doesn't work in the second when you get for example 1 1 3 1 1 2 because i can't figure out a good way to handle so much variations especially if K is bigger than 3 and the limit is 50. My version:
N, K, M = map(int, input().split())
niz = list(map(int, input().split()))
nizk = list(range(1, K+1))
izlazi = []
for r in range(0, M):
operacija = list(map(int, input().split()))
index = 0
if operacija[0] == 2:
nizkk = []
for z in range(0, len(nizk)):
if nizk[z] in niz:
continue
else:
izlazi.append(-1)
break
for p in range(0, N):
if niz[p] not in nizkk:
nizkk.append(niz[p])
nizkk.sort()
if nizkk == nizk:
index = p
izlazi.append(index+1)
break
else:
continue
else:
index, repl = map(int, operacija[1:])
niz[index - 1] = repl
print(izlazi)
In the first line of the input there should be N, K, M (1 <= N, M <= 100k, 1 <= K <= 50, you don't need to actually check this the numbers that are tested will always be in those ranges). In the second line of input you put a list of numbers which are the lenght of N you entered earlier. M is the number of operations you will do in the following lines of input. There can be 2 operations. If you enter 1 p v(p = index of number you want to replace, v the number you replace it with) or if you enter 2 it needs to find the shortest array of numbers defined by range(1, K+1) in the list of numbers you entered in line 2 and possibly changed with operation 1. If it doesn't exist it should output -1 if it does it should output lenght of numbers in the array you look in(numbers can be like 2, 1, 3 if you're looking for 1, 2, 3, also if you're looking for 1, 2, 3 etc and you have 2, 1, 1, 3 as the shortest one that is the solution and it's lenght is 4). Also the replacement operation doesnt count from 0 but from 1. So watch out when managing lists.
These are the examples you can input in the program ulaz = input, izlaz = ouput:
I have the following idea:
Min length sequence either starts from first element or does not contain first element and hence equals to min length of the same sequence without first element.
So we have recursion here.
For sequence [1,1,3,2,1,1] and [1,2,3] we will have:
Min length from start element [1,1,3,2,1,1] is 4
Min length from start element __[1,3,2,1,1] is 3
Min length from start element ____[3,2,1,1] is 3
Min length from start element ______[2,1,1] is -1
Can stop here.
Result is minimum for [4,3,3] = 3
You have already implemented the part for min length, if it starts from the first element. Need now extract it as a function and create a recursive function.
Some metacode:
function GetMinLength(seq)
{
minLengthFromFirstElement = GetMinLenthFromFirstElement(seq)
minLengthFromRest = GetMinLength(seq[1:]) //recusive call
return Min(minLengthFromFirstElement, minLengthFromRest )//-1 results should not count, add extra code to handle it
}
Unfortunately I don't know python, but I can provide code on F# in case you need it.
EDIT:
Try this:
N, K, M = map(int, input().split())
niz = list(map(int, input().split()))
nizk = list(range(1, K+1))
izlazi = []
def GetMinLengthStartingFromFirstElement(seq):
nizkk = []
for z in range(0, len(seq)):
if seq[z] in nizk:
continue
else:
return -1
for p in range(0, len(seq)):
if seq[p] not in nizkk:
nizkk.append(seq[p])
nizkk.sort()
if nizkk == nizk:
index = p
return index+1
else:
continue
return -1
def GetMinLength(seq):
if len(seq) == 0:
return -1
else:
curMinLength = GetMinLengthStartingFromFirstElement(seq)
if curMinLength == -1:
return -1
minLengthFromRest = GetMinLength(seq[1:])
if minLengthFromRest > -1:
return min(curMinLength,minLengthFromRest)
else:
return curMinLength;
for r in range(0, M):
operacija = list(map(int, input().split()))
index = 0
if operacija[0] == 2:
minLength = GetMinLength(niz)
izlazi.append(minLength)
else:
index, repl = map(int, operacija[1:])
niz[index - 1] = repl
print(izlazi)

Categories