Remove consecutive duplicate characters of even count from the given string - python

I'm trying to solve a problem where I get the string as input and then delete the duplicate characters of even count.
Input:azxxzyyyddddyzzz
Output: azzz
can you help me with this.
My Attempt is working fine for removing duplicate characters but I'm stuck at how to remove duplicate characters of even count
# Utility function to convert string to list
def toMutable(string):
temp = []
for x in string:
temp.append(x)
return temp
# Utility function to convert string to list
def toString(List):
return ''.join(List)
# Function to remove duplicates in a sorted array
def removeDupsSorted(List):
res_ind = 1
ip_ind = 1
# In place removal of duplicate characters
while ip_ind != len(List):
if List[ip_ind] != List[ip_ind-1]:
List[res_ind] = List[ip_ind]
res_ind += 1
ip_ind+=1
# After above step string is efgkorskkorss.
# Removing extra kkorss after string
string = toString(List[0:res_ind])
return string
# Function removes duplicate characters from the string
# This function work in-place and fills null characters
# in the extra space left
def removeDups(string):
# Convert string to list
List = toMutable(string)
# Sort the character list
List.sort()
# Remove duplicates from sorted
return removeDupsSorted(List)
# Driver program to test the above functions
string = "geeksforgeeks"
print removeDups(string)

Here's an attempt with itertools.groupby. I'm not sure if it can be done with better time complexity.
from itertools import groupby
def rm_even(s):
to_join = []
for _, g in groupby(s):
chars = list(g)
if len(chars) % 2:
to_join.extend(chars)
if to_join == s:
return ''.join(to_join)
return rm_even(to_join)
Demo:
>>> rm_even('azxxzyyyddddyzzz')
>>> 'azzz'
>>> rm_even('xAAAAx')
>>> ''

Count the letters with Counter and remove the ones that have even count:
from collections import Counter
word = 'azxxzyyyddddyzzz'
count = Counter(word) # Counter({'z': 5, 'y': 4, 'd': 4, 'x': 2, 'a': 1})
for key, value in count.items():
if value%2 == 0:
word = word.replace(key, "")
print(word) # 'azzzzz'

def remove_even_dup(string):
spans = []
for idx, letter in enumerate(string):
if not len(spans) or spans[-1][0] != letter:
spans.append((letter, {idx}))
else:
spans[-1][1].add(idx)
# reverse the spans so we can use them as a stack
spans = list(reversed(spans))
visited = []
while len(spans):
letter, indexes = spans.pop()
if len(indexes) % 2 != 0:
visited.append((letter, indexes))
else:
# if we have any previous spans we might need to merge
if len(visited):
prev_letter, prev_indexes = visited[-1]
next_letter, next_indexes = spans[-1]
# if the previous one and the next one have the same letter, merge them
if prev_letter == next_letter:
# remove the old
visited.pop()
spans.pop()
# add the new to spans to be visited
spans.append((letter, prev_indexes | next_indexes))
to_keep = { idx for _, indexes in visited for idx in indexes }
return ''.join(letter for idx, letter in enumerate(string) if idx in to_keep)

I used Collection because it is easy to delete and we have to convert into the string.
import java.util.*;
public class RemoveEvenCount {
public static void main(String[] args) {
//String a="azxxzyyyddddyzzz";
String a="xAAAAx";
ArrayList a2=new ArrayList<>();
for(int i=0;i<a.length();i++)
{
a2.add(a.charAt(i));
}
a2=removeData(a2);
System.out.print(a2);
}
public static ArrayList removeData(ArrayList a2)
{
if(a2.size()==2)
{
if(a2.get(0)==a2.get(1))
return null;
}
for(int i=0;i<a2.size();i++)
{
int count =1;
for(int j=0;j<a2.size()-1;j++)
{
if(a2.get(j)==a2.get(j+1))
{
count++;
}else if(count%2==0)
{
for(int k=0;k<count;k++)
{
a2.remove(j-k);
}
return removeData(a2);
}
Count=1
}
}
return a2;
}
}

Related

Rewrite path between nodes as data structure from string in python

I am trying to convert a string which shows an optimal path between nodes from a string to a data structure.
At each node A, B, C, ... my scanner either tells me a result of "Triple, Double, Single or none". Dependent on my result the optimal path tells me what node I should go to next.
i.e:
A double B triple
A double B double C double D triple
A double B double C double D double E double
A double B double C single D double
all paths
I want to convert a collection of these strings into a data structure like the following:
checkMap: {
node: "A",
double: {
node: "B",
double: {
node: "C",
double: {
node: "D",
double: {
node: "E"
}
},
single: {
node: "D"
}
}
},
single: {
node: "F"
}
}
This maps out which nodes connect to which and what result (single, double...) takes you there. If there are no nodes continuing that shows it terminates there.
My current attempt:
import csv which contains all routes as a pandas df, and put all the routes into a list and remove the final result (as result at termination point is not needed in structure):
paths = []
for i in df[0].str.split(" "):
if len(i) > 2:
paths.append(i[:-1])
Remove any duplicates (removing last result creates duplicates):
remove = []
for i in range(len(paths)):
for j in range(i + 1, len(paths)):
if paths[i] == paths[j]:
remove.append(j)
break
for i in sorted(remove, reverse=True):
del paths[i]
Then I remove paths which are subsets of other paths to simplify the problem:
remove = []
for i in range(len(paths)):
for j in range(i + 1, len(paths)):
if set(paths[i]).issubset(paths[j]):
remove.append(i)
break
for i in sorted(remove, reverse=True):
del paths[i]
Then it is here I am struggling to achieve the end result. At this point, I have the following list
simplified list
I made a recursive function which outputs each of the paths, but I can't think how to account for when the path splits into two (or more) paths for different results i.e. at A double and A single
def thing(arr, string = "", count = -1):
if len(arr) == 1:
string = string + 'node: "' + arr[0] + '"}'
string = string + count*"}" + "\n"
print(string)
return string
count = count + 1
string = string + 'node: "' + arr[0] + '",\n'
string = string + arr[1] + ': {\n'
thing(arr[2:], string, count)
return string
for i in range(len(paths)):
routes.append(thing(paths[i]))

How can I create a new list when giving intergers, and have to return hexadecimal

Given the following list:
list = [2,10,10,10,4,5]
How can I write a function that returns the output:
output = 210AA:45
I was working with this code so far, but don't know what else to add so that once a number between 10 and 15 is repeated, return the repeated number in its hexadecimal form as in the output
def int_to_string(data):
string = ""
for i in data:
hexadecimal = hex(i)
string += hexadecimal[2:]
string[0] = 15
return string
Use a list [] instead of a string ""
strings are immutable and don't support index lookup and assignment.
append the hex val and then edit the first index as you see fit to get your result
and retun a joined list with
''.join(#ur_lst)
A dictionary describing the mapping between decimal and hex could add readability.
Remark: don't shadow the name of build-functions, in this case list. See doc for a complete list.
lst = [2,10,10,10,4,5,13,15,0] # <- new testing list
# dictionary for conversion
num2hex = {i: str(i) for i in range(10)}
num2hex.update(zip(range(10, 16), "ABCDEF"))
# conversion list -> str
res = ''
consecutve_hex, is_last_hex = 0, False
for d in lst:
if 10 <= d <= 15:
consecutive_hex += 1
is_last_hex = False
if consecutive_hex > 1:
res += num2hex[d]
else:
res += str(d)
else:
if not is_last_hex:
if res:
res += ':'
consecutive_hex = 0
is_last_hex = True
res += str(d)
print(res)
#210AA:4513F:0

How to replace string in order

I want to replace some value in order
for example, below is a sample of xpath
/MCCI_IN200100UV01[#ITSVersion='XML_1.0'][#xsi:schemaLocation='urn:hl7-org:v3 MCCI_IN200100UV01.xsd']
/PORR_IN049016UV[r]/controlActProcess[#classCode='CACT']
[#moodCode='EVN']/subject[#typeCode='SUBJ'][1]/investigationEvent[#classCode='INVSTG']
[#moodCode='EVN']/outboundRelationship[#typeCode='SPRT'][relatedInvestigation/code[#code='2']
[#codeSystem='2.16.840.1.113883.3.989.2.1.1.22']][r]/relatedInvestigation[#classCode='INVSTG']
[#moodCode='EVN']/subjectOf2[#typeCode='SUBJ']/controlActEvent[#classCode='CACT']
[#moodCode='EVN']/author[#typeCode='AUT']/assignedEntity[#classCode='ASSIGNED']/assignedPerson[#classCode='PSN']
[#determinerCode='INSTANCE']/name/prefix[1]/#nullFlavor",
and, I would like to extract [r] in order and to replace from [0] to [n] depending on the number of elements.
how can I replace [r] ?
const txt = `/MCCI_IN200100UV01[#ITSVersion='XML_1.0'][#xsi:schemaLocation='urn:hl7-org:v3 MCCI_IN200100UV01.xsd']
/PORR_IN049016UV[r]/controlActProcess[#classCode='CACT']
[#moodCode='EVN']/subject[#typeCode='SUBJ'][1]/investigationEvent[#classCode='INVSTG']
[#moodCode='EVN']/outboundRelationship[#typeCode='SPRT'][relatedInvestigation/code[#code='2']
[#codeSystem='2.16.840.1.113883.3.989.2.1.1.22']][r]/relatedInvestigation[#classCode='INVSTG']
[#moodCode='EVN']/subjectOf2[#typeCode='SUBJ']/controlActEvent[#classCode='CACT']
[#moodCode='EVN']/author[#typeCode='AUT']/assignedEntity[#classCode='ASSIGNED']/assignedPerson[#classCode='PSN']
[#determinerCode='INSTANCE']/name/prefix[1]/#nullFlavor",`;
const count = (txt.match(/\[r\]/g) || []).length; // count occurrences using RegExp
let replacements; // set replacement values in-order
switch (count) {
case 0:
break
case 1:
replacements = ["a"];
break;
case 2:
replacements = ["___REPLACEMENT_1___", "___REPLACEMENT_2___"];
break;
case 3:
replacements = ["d", "e", "f"];
break;
}
let out = txt; // output variable
for (let i = 0; i < count; i++) {
out = out.replace("[r]", replacements[i], 1); // replace each occurrence one at a time
}
console.log(out);
With str.replace(). For example:
>>> 'test[r]test'.replace('[r]', '[0]')
'test[0]test'
Here's the docs on it.

python : Noob IndexError

I am currently trying to create a code that can scan a string, put the position of each letter found in a list associated to the letter (ex : if you find a S as the 35, 48 and 120 letter of the string, it will put 35, 48, and 120 in a list for the letter S). It will then put this list in a dictionary as a value with S for key.
My problem is simple, I have an IndexError: list assignment index out of range when I try to put the value in the list, but I cant find out why.
string = "Squalalanoussommespartisetjetedteste"
taille = len(string)
dico = dict()
dico = {}
i = 0
for i in range(taille):
if string[i] == "A" or string[i] == "a" :
va = 0
valA = []
valA[va] = i
va = va + 1
print(valA)
I apologize for my poor English, and thank by advance for the help.
You don't need to specify an index while pushing an item to a list in python. Try this:
for i in range(taille):
if string[i] == "A" or string[i] == "a" :
valA = []
valA.append(i)
print(valA)
You are getting this error in these lines
va = 0
valA = []
valA[va] = i
valA is blank list here, with zero elements, so when you try to assign a value to its 0 index, it raises IndexError.
Also to get indexes for each character you can directly loop over string, like
s = "Squalalanoussommespartisetjetedteste"
d = dict()
for i, c in enumerate(s):
d.setdefault(c.lower(), []).append(i)
print d
I found some errors in the code.
The index error is because you tried to call 0th position of an empty list.
valA = []
The list is empty. Then you tried to replace value at the 0th position when there is no 0th position
valA[va] = i
I made some changes to the code. In the ninth line you initialize an empty list. You should do that before for loop. Otherwise for loop initiate it everytime and you lose the value in the previous loop.
here is the modified code.
string = "Squalalanoussommespartisetjetedteste"
taille = len(string)
dico = dict()
dico = {}
i = 0
valA = []
for i in range(taille):
if string[i] == "A" or string[i] == "a":
valA.append(i)
print(valA)
The output i got is
[3, 5, 7, 19]
Though you may use straightforward approach, Python has some usefull modules that may help. For example
import collections
s = "Squalalanoussommespartisetjetedteste"
result = collections.defaultdict(list)
for i,char in enumerate(s):
result[char].append(i)
result would contain a dictionary with string characters as keys and lists if char's indexes as items.
You are redefining variables below everytime. So move them to out of loop.
va = 0
valA = []
Also use insert method for list. (You can use insert for when you need to use define index in list. otherwise append is enough)
so final code :
string = "Squalalanoussommespartisetjetedteste"
taille = len(string)
dico = dict()
dico = {}
i = 0
va = 0
valA = []
for i in range(taille):
if string[i] == "A" or string[i] == "a" :
valA.insert(va, i)
va = va + 1
print(valA)
index error, because array valA is empty array, that means there are no indexes...
use function append and declare array valA outside the loop...
string = "Squalalanoussommespartisetjetedteste"
taille = len(string)
dico = dict()
dico = {}
i = 0
valA = []
for i in range(taille):
if string[i] == "A" or string[i] == "a" :
valA.append(i)
print(valA)

find the index of element the number of occurence in string

A Char_Record is a 3 item list [char, total, pos_list] where
char is a one character string
total is a Nat representing the number of occurrences of char
pos_list is a list of Nat representing the indices of char
Using the function build_char_records() should produce a sorted list with every character represented (lowercase).
For example:
>>>build_char_records('Hi there bye')
['',2,[2,8]]
['b',1,[9]]
['e',3,[5,7,11]]
['h',2[0,4]]
['i',1,[1]]
['r',1,[6]]
['t',1,[3]]
['y',1,[10]]
I just wrote it like this , I don't know how to do it, someone help please. Thanks.
def build_char_records(s):
s=sorted(s)
a=[]
for i in range(len(s)):
I think that the other answers given thus far are better answers from an overall programming perspective, but based on your question I think this answer is appropriate for your skill level
def build_char_records(phrase):
phrase = phrase.lower()
resultList = []
for character in phrase: ## iterates through the phrase
if character not in resultList:
resultList.append(character) ## This adds each character to the list
## if it is not already in the list
resultList.sort() ## sorts the list
for i in range(len(resultList)): ## goes through each unique character
character = resultList[i] ## the character in question
tphrase = phrase ## a copy of the phrase
num = phrase.count(character) ## the number of occurences
acc = 0 ## an accumulator to keep track of how many we've found
locs = [] ## list of the locations
while acc < num: ## while the number we've found is less than how many
## there should be
index = tphrase.find(character) ## finds the first occurance of the character
tphrase = tphrase[index+1:] ## chops off everything up to and including the
## character
if len(locs) != 0: ## if there is more than one character
index = locs[acc-1] + index + 1 ## adjusts because we're cutting up the string
locs.append(index)## adds the index to the list
acc += 1 ## increases the accumulator
resultList[i] = [character, num, locs] ## creates the result in the proper spot
return resultList ## returns the list of lists
print build_char_records('Hi there bye')
This will print out [[' ', 2, [2, 8]], ['b', 1, [9]], ['e', 3, [5, 7, 11]], ['h', 2, [0, 4]], ['i', 1, [1]], ['r', 1, [6]], ['t', 1, [3]], ['y', 1, [10]]]
Here is a slightly shorter, cleaner version
def build_char_records(phrase):
phrase = phrase.lower()
resultList = []
for character in phrase:
if character not in resultList:
resultList.append(character)
resultList.sort()
for i in range(len(resultList)):
tphrase = phrase
num = phrase.count(resultList[i])
locs = []
for j in range(num):
index = tphrase.find(resultList[i])
tphrase = tphrase[index+1:]
if len(locs) != 0:
index = locs[acc-1] + index + 1
locs.append(index)
resultList[i] = [resultList[i], num, locs]
return resultList
print build_char_records('Hi there bye')
Using only list, this is what you can do:
def build_char_records(s):
records = [] # Create a list to act as a dictionary
for idx, char in enumerate(s):
char = char.lower()
current_record = None # Try to find the record in our list of records
for record in records: # Iterate over the records
if record[0] == char: # We find it!
current_record = record # This is the record for current char
break # Stop the search
if current_record is None: # This means the list does not contain the record for this char yet
current_record = [char, 0, []] # Create the record
records.append(current_record) # Put the record into the list of records
current_record[1] += 1 # Increase the count by one
current_record[2].append(idx) # Append the position of the character into the list
for value in records: # Iterate over the Char_Record
print value # Print the Char_Record
Or, if you need to sort it, you can do what #Dannnno said, or as an example, it can be sorted in this way (although you might have not learned about lambda):
records.sort(key=lambda x: x[0])
Just put that before printing the records.
Or, you can do it using dict and list:
def build_char_records(s):
record = {} # Create an empty dictionary
for idx, char in enumerate(s): # Iterate over the characters of string with the position specified
char = char.lower() # Convert the character into lowercase
if char not in record: # If we have not seen the character before, create the Char_Record
record[char] = [char,0,[]] # Create a Char_Record and put it in the dictionary
record[char][1] += 1 # Increase the count by one
record[char][2].append(idx) # Append the position of the character into the list
for value in record.values(): # Iterate over the Char_Record
print value # Print the Char_Record
from collections import defaultdict
def build_char_records(s):
cnt = defaultdict(int)
positions = defaultdict(list)
for i,c in enumerate(s):
cnt[c] += 1
positions[c].append(i)
return [ [c, cnt[c], positions[c]] for c in cnt.keys() ]

Categories