replace each character with the first greater character after it - python

I am trying to replace each character with the next greater character after it and if there is no greater character after it then replace it by '#'
if I have a circular list of characters [K, M, Y, R, E, J, A]
the output should be [M, Y, #, Y, J, K, K]
'M is greater than k so replace K with M and Y is greater than M so replace M with Y and so one ( greater here means comes after it )'
this is the code that I have tried but it gives wrong output
def que1(input_list):
for i in range (len (input_list)-1) :
j=i+1
for j in range (len(input_list)-1):
if input_list[i]<input_list[j]:
input_list[i]=input_list[j]
if input_list[i]>input_list[j]:
input_list[i]='#'
return input_list

Another way to do it :
def que1(i_list):
input_list=i_list*2
output_list=[]
for i in range (len (i_list)) :
found=False
for j in range (i+1,len(input_list)-1):
if input_list[i]<input_list[j]:
output_list.append(input_list[j])
found=True
break
if not found:
output_list.append('#')
return output_list
output:
['M', 'Y', '#', 'Y', 'J', 'K', 'K']

The following code should do what you want.
def que1(input_list):
output_list = []
# loop through the input list with index
for index, c in enumerate(input_list):
# split list at c and create new list
# [all greater characters after c, all greater character before c]
tmp = [i for i in input_list[index:] if i > c] + [i for i in input_list[:index] if i > c]
# if list empty there is no greater character
if len(tmp) == 0:
output_list.append('#')
# else choose the first greater character
else:
output_list.append(tmp[0])
return output_list
Input: ['K', 'M', 'Y', 'R', 'E', 'J', 'A']
Output: ['M', 'Y', '#', 'Y', 'J', 'K', 'K']

Here is another way to do it.
def next_greatest(data):
out = []
for idx in range(len(data)):
char = data[idx]
cs = iter(data[idx + 1:] + data[:idx])
while True:
try:
curr = next(cs)
except StopIteration:
out.append("#")
break
if curr > char:
out.append(curr)
break
return out
next_greatest(chars)
>> ['M', 'Y', '#', 'Y', 'J', 'K', 'K']

Related

how to separate alternating digits and characters in string into dict or list?

'L134e2t1C1o1d1e1'
the original string is "LeetCode"
but I need to separate strings from digits, digits can be not only single-digit but also 3-4 digits numbers like 345.
My code needs to separate into dict of key values; keys are characters and numbers is the digit right after the character. Also create 2 lists of separate digits, letters only.
expected output:
letters = ['L', 'e', 't', 'C', 'o', 'd', 'e']
digits = [134,2,1,1,1,1,1]
This code is not properly processing this.
def f(s):
d = dict()
letters = list()
# letters = list(filter(lambda x: not x.isdigit(), s))
i = 0
while i < len(s):
print('----------------------')
if not s[i].isdigit():
letters.append(s[i])
else:
j = i
temp = ''
while j < len(s) and s[j].isdigit():
j += 1
substr = s[i:j]
print(substr)
i += 1
print('----END -')
print(letters)
With the following modification your function separates letters from digits in s:
def f(s):
letters = list()
digits = list()
i = 0
while i < len(s):
if not s[i].isdigit():
letters.append(s[i])
i += 1
else:
j = i
temp = ''
while j < len(s) and s[j].isdigit():
j += 1
substr = s[i:j]
i = j
digits.append(substr)
print(letters)
print(digits)
f('L134e2t1C1o1d1e1')
As said in my comments you didn't update i after the inner loop terminates which made i go back to a previous and already processed index.
If I would be limited to not use regex I would do it following way
text = 'L134e2t1C1o1d1e1'
letters = [i for i in text if i.isalpha()]
digits = ''.join(i if i.isdigit() else ' ' for i in text).split()
print(letters)
print(digits)
output
['L', 'e', 't', 'C', 'o', 'd', 'e']
['134', '2', '1', '1', '1', '1', '1']
Explanation: for letters I use simple list comprehension with condition, .isalpha() is str method which check if string (in this consisting of one character) is alphabetic. For digits (which should be rather called numbers) I replace non-digits using single space, turn that into string using ''.join then use .split() (it does split on one or more whitespaces). Note that digits is now list of strs rather than ints, if that is desired add following line:
digits = list(map(int,digits))
Your string only had two e's, so I've added one more to complete the example. This is one way you could do it:
import re
t = 'L1e34e2t1C1o1d1e1'
print(re.sub('[^a-zA-Z]', '', t))
Result:
LeetCode
I know you cannot use regex, but to complete this answer, I'll just add a solution:
def f(s):
d = re.findall('[0-9]+', s)
l = re.findall('[a-zA-Z]', s)
print(d)
print(l)
f(t)
Result:
['134', '2', '1', '1', '1', '1', '1']
['L', 'e', 't', 'C', 'o', 'd', 'e']
You edited your question and I got a bit confused, so here is a really exhaustive code giving you a list of letters, list of the numbers, the dict with the number associated with the number, and finally the sentence with corresponding number of characters ...
def f(s):
letters = [c for c in s if c.isalpha()]
numbers = [c for c in s if c.isdigit()]
mydict = {}
currentKey = ""
for c in s:
print(c)
if c.isalpha():
mydict[c] = [] if c not in mydict.keys() else mydict[c]
currentKey = c
elif c.isdigit():
mydict[currentKey].append(c)
sentence = ""
for i in range(len(letters)):
count = int(numbers[i])
while count > 0:
sentence += letters[i]
count -= 1
print(letters)
print(numbers)
print(mydict)
print(sentence)
letters = []
digits = []
dig = ""
for letter in 'L134e2t1C1o1d1e1':
if letter.isalpha():
# do not add empty string to list
if dig:
# append dig to list of digits
digits.append(dig)
dig = ""
letters.append(letter)
# if it is a actual letter continue
continue
# add digits to `dig`
dig = dig + letter
Try this. The idea is to skip all actual letters and add the digits to dig.
I know there's an accepted answer but I'll throw this one in anyway:
letters = []
digits = []
lc = 'L134e2t1C1o1d1e1'
n = None
for c in lc:
if c.isalpha():
if n is not None:
digits.append(n)
n = None
letters.append(c)
else:
if n is None:
n = int(c)
else:
n *= 10
n += int(c)
if n is not None:
digits.append(n)
for k, v in zip(letters, digits):
dct.setdefault(k, []).append(v)
print(letters)
print(digits)
print(dct)
Output:
['L', 'e', 't', 'C', 'o', 'd', 'e']
[134, 2, 1, 1, 1, 1, 1]
{'L': [134], 'e': [2, 1], 't': [1], 'C': [1], 'o': [1], 'd': [1]}

How to sort sections of a list: [duplicate]

This question already has answers here:
Sort a part of a list in place
(3 answers)
Closed 11 months ago.
I’m trying to figure out how to sort a list but not all at once like in:
list.sort()
But instead I want to sort the first 3, then the next 3 and so on.
Let’s say my list is the following
list = [ F, V, T, O, D, Q, I, P, M]
Id want the out put to look like this:
[F, T, V, D, O, Q, I, M, P]
Does anyone know how I could go about doing this?
You can sort a slice of a list, and use slice assignment to replace it in the original list:
>>> my_list = ['F', 'V', 'T', 'O', 'D', 'Q', 'I', 'P', 'M']
>>> for i in range(len(my_list) // 3):
... my_list[i*3:i*3+3] = sorted(my_list[i*3:i*3+3])
...
>>> my_list
['F', 'T', 'V', 'D', 'O', 'Q', 'I', 'M', 'P']
Another option would be to build a whole new list with sum and just assign it to my_list at the end (whether or not this is equivalent depends on whether there are other references to my_list anywhere):
>>> my_list = ['F', 'V', 'T', 'O', 'D', 'Q', 'I', 'P', 'M']
>>> my_list = sum((sorted(my_list[i*3:i*3+3]) for i in range(len(my_list) // 3)), [])
>>> my_list
['F', 'T', 'V', 'D', 'O', 'Q', 'I', 'M', 'P']
my_list = ["F", "V", "T", "O", "D", "Q", "I", "P", "M"]
slice = 3
sorted_list = sum([sorted(my_list[i:i+slice]) for i in range(0, len(my_list), slice)], [])
# ['F', 'T', 'V', 'D', 'O', 'Q', 'I', 'M', 'P']
Just for fun a silly hack you shouldn't rely on:
i = iter(range(len(lst)))
lst.sort(key=lambda x: (next(i) // 3, x))
Benchmark results for list random.choices(ascii_uppercase, k=30_000):
6.10 ms Samwise
5.66 ms Samwise_juanpa
11.63 ms Kelly
10.94 ms Kelly_juanpa
1.81 ms Kelly6
Benchmark code (Try it online!):
def Samwise(my_list):
for i in range(len(my_list) // 3):
my_list[i*3:i*3+3] = sorted(my_list[i*3:i*3+3])
return my_list
def Samwise_juanpa(my_list):
for i in range(len(my_list) // 3):
sl = slice(i*3, i*3+3)
my_list[sl] = sorted(my_list[sl])
return my_list
def Kelly(lst):
i = iter(range(len(lst)))
lst.sort(key=lambda x: (next(i) // 3, x))
return lst
def Kelly_juanpa(lst):
pairs = sorted([(i//3, x) for i, x in enumerate(lst)])
return [x for _, x in pairs]
def Kelly6(lst):
result = []
for a, b, c in zip(*[iter(lst)]*3):
if b < a:
if c < b:
result += c, b, a
elif c < a:
result += b, c, a
else:
result += b, a, c
else:
if c < a:
result += c, a, b
elif c < b:
result += a, c, b
else:
result += a, b, c
result += sorted(lst[len(lst) // 3 * 3:])
return result
funcs = [
Samwise,
Samwise_juanpa,
Kelly,
Kelly_juanpa,
Kelly6,
]
from timeit import default_timer as timer
from string import ascii_uppercase
import random
for _ in range(3):
lst = random.choices(ascii_uppercase, k=30_000)
previous = None
for func in funcs:
times = []
for _ in range(20):
copy = lst[:]
t0 = timer()
result = func(copy)
t1 = timer()
times.append(t1 - t0)
print('%5.2f ms ' % (min(times) * 1e3), func.__name__) #, len(result), previous is None or result == previous)
assert previous is None or result == previous
previous = result
print()

Python: How to check if element of string is in a string and print the not included string elements?

I want to check each list element of c in alphabet and print the letters of the alphabet, which are not in a list element of c.
For example, shall the first list element of c "aa" print all letters of alphabet in a string excluding the letter a.
alphabet = "abcdefghijklmnopqrstuvwxyz"
c = ['aa', 'bb', 'zz']
for x in c:
if x in alphabet:
print(alphabet)
else:
print('not an element of alphabet')
Something like that:
alphabet = "abcdefghijklmnopqrstuvwxyz"
cases = ['aa', 'bb', 'zz']
for case in cases:
missing_letters = []
for letter in alphabet:
if letter not in case:
missing_letters.append(letter)
print(f"Case {case} misses following alphabeth letters {missing_letters}")
Output:
Case aa misses following alphabeth letters ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
If you are sure that the elements in c are all in the format of 'xx' like in your sample, then the following is a solution:
alphabet = "abcdefghijklmnopqrstuvwxyz"
c = ['ad', 'bb', 'zz','ad', 'bt', 'uz']
for x in c:
new_alph = alphabet
for char in x:
new_alph = new_alph.replace(char,'')
if new_alph == alphabet:
print('not an element of alphabet')
else:
print(new_alph)
Output:
bcefghijklmnopqrstuvwxyz
acdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxy
bcefghijklmnopqrstuvwxyz
acdefghijklmnopqrsuvwxyz
abcdefghijklmnopqrstvwxy
Another way is to use translate to make the code more compact:
alphabet = "abcdefghijklmnopqrstuvwxyz"
c = ['ad', 'bb', 'zz','ad', 'bt', 'uz']
for x in c:
new_alph = alphabet.translate({ord(char): '' for char in x})
if new_alph == alphabet:
print('not an element of alphabet')
else:
print(new_alph)
Output:
bcefghijklmnopqrstuvwxyz
acdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxy
bcefghijklmnopqrstuvwxyz
acdefghijklmnopqrsuvwxyz
abcdefghijklmnopqrstvwxy
As long as the strings in c are only 2 chars this will work
alphabet = "abcdefghijklmnopqrstuvwxyz"
c = ['aa', 'bb', 'zz']
for x in c:
if x[0] in alphabet or x[1] in alphabet:
alphabet.replace(x[0], '').replace(x[1], '')
else:
print('not an element of alphabet')

How do I alphabetically sort an array of strings without any sort functions? Python

When solving the following problem:
"Assuming you have a random list of strings (for example: a, b, c, d, e, f, g), write a program that will sort the strings in alphabetical order.
You may not use the sort command."
I run into the problem of running strings through the following code, which sometimes gets me duplicated strings in final list
I am fairly new to python and our class just started to look at numpy, and functions in that module, and im not sure of any being used in the code (except any sort function).
import numpy as np
list=[]
list=str(input("Enter list of string(s): "))
list=list.split()
print() # for format space purposes
listPop=list
min=listPop[0]
newFinalList=[]
if(len(list2)!=1):
while(len(listPop)>=1):
for i in range(len(listPop)):
#setting min=first element of list
min=listPop[0]
if(listPop[i]<=min):
min=listPop[i]
print(min)
listPop.pop(i)
newFinalList.append(min)
print(newFinalList)
else:
print("Only one string inputted, so already alphabatized:",list2)
Expected result of ["a","y","z"]
["a","y","z"]
Actual result...
Enter list of string(s): a y z
a
a
a
['a', 'a', 'a']
Enter list of string(s): d e c
d
c
d
d
['c', 'd', 'd']
Selection sort: for each index i of the list, select the smallest item at or after i and swap it into the ith position. Here's an implementation in three lines:
# For each index i...
for i in range(len(list)):
# Find the position of the smallest item after (or including) i.
j = list[i:].index(min(list[i:])) + i
# Swap it into the i-th place (this is a no-op if i == j).
list[i], list[j] = list[j], list[i]
list[i:] is a slice (subset) of list starting at the ith element.
min(list) gives you the smallest element in list.
list.index(element) gives you the (first) index of element in list.
a, b = b, a atomically swaps the values of a and b.
The trickiest part of this implementation is that when you're using index to find the index of the smallest element, you need to find the index within the same list[i:] slice that you found the element in, otherwise you might select a duplicate element in an earlier part of the list. Since you're finding the index relative to list[i:], you then need to add i back to it to get the index within the entire list.
You can implement Quick sort for same:
def partition(arr,low,high):
i = ( low-1 )
pivot = arr[high]
for j in range(low , high):
if arr[j] <= pivot:
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
def quickSort(arr,low,high):
if low < high:
pi = partition(arr,low,high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
arr = ['a', 'x', 'p', 'o', 'm', 'w']
n = len(arr)
quickSort(arr,0,n-1)
print ("Sorted list is:")
for i in range(n):
print ("%s" %arr[i]),
output:
Sorted array is:
a m o p w x
Mergesort:
from heapq import merge
from itertools import islice
def _ms(a, n):
return islice(a,n) if n<2 else merge(_ms(a,n//2),_ms(a,n-n//2))
def mergesort(a):
return type(a)(_ms(iter(a),len(a)))
# example
import string
import random
L = list(string.ascii_lowercase)
random.shuffle(L)
print(L)
print(mergesort(L))
Sample run:
['h', 'g', 's', 'l', 'a', 'f', 'b', 'z', 'x', 'c', 'r', 'j', 'q', 'p', 'm', 'd', 'k', 'w', 'u', 'v', 'y', 'o', 'i', 'n', 't', 'e']
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

prints results only when string item index == list item index

I've been working on a little project of mine lately, but I've run into a problem that I'm stuck at. I've already checked various places, but I couldn't really find what I'm looking for. This is my code:
special_alphabet = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
v, w, x, y, z]
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k','l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
name = input('Please insert your name: ')
item_alphabet = -1
item_special_alphabet = -1
index = -1
for item in name:
item_alphabet = item_alphabet + 1
item_special_alphabet = item_special_alphabet + 1
index = index + 1
if alphabet[item_alphabet] == name[index]:
print(special_alphabet[item_special_alphabet])
The special_alphabet list contains the special characters that I have in variables. I didn't display them because they're too long, but they're there.
The problem I'm having right now is that when I run this code and type in my input, it does actually check the 'name' (string) I've inserted, it just does it in order of the list(alphabet basically). So when I enter: Amine, it only returns the special character for A (because it's the first (0) in both the string and the list) and E (same reason, just it's fifth.)
What I'm looking for is how to make it go through the whole list without any order whatsoever and check all the items in it before running the if statement and printing out the special characters.
Thank you in advance.
You can use str.maketrans() and str.translate() for these kinds of translation jobs:
trans_tab = str.maketrans(dict(zip(alphabet, special_alphabet)))
name = input('Please insert your name: ')
translated_name = name.translate(trans_tab)
print(translated_name)
If you pass str.maketrans() a single dictionary argument that consists of strings of length 1 as keys and arbitrary length strings as values, it'll build you a translation table usable with str.translate(), which creates a new copy of the string where each character has been mapped through the given translation table.
For example:
In [15]: trans = str.maketrans({
...: 'A': 'A ',
...: 'm': 'M ',
...: 'i': 'I ',
...: 'n': 'N ',
...: 'e': 'E '
...: })
In [16]: input("> ").translate(trans)
> Amine
Out[16]: 'A M I N E '
A dictionary of alphabet and spacial alphabet may be a best design
in your case try;
for item in name:
ind = alphabet.find(item)
if ind != -1:
print(special_alphabet[ind])

Categories

Resources