Why is this not correct? (codeeval challenge)PYTHON - python

This is what I have to do https://www.codeeval.com/open_challenges/140/
I've been on this challenge for three days, please help. It it is 85-90 partially solved. But not 100% solved... why?
This is my code:
import sys
test_cases = open(sys.argv[1], 'r')
for test in test_cases:
saver=[]
text=""
textList=[]
positionList=[]
num=0
exists=int()
counter=0
for l in test.strip().split(";"):
saver.append(l)
for i in saver[0].split(" "):
textList.append(i)
for j in saver[1].split(" "):
positionList.append(j)
for i in range(0,len(positionList)):
positionList[i]=int(positionList[i])
accomodator=[None]*len(textList)
for n in range(1,len(textList)):
if n not in positionList:
accomodator[n]=textList[len(textList)-1]
exists=n
for item in positionList:
accomodator[item-1]=textList[counter]
counter+=1
if counter>item:
accomodator[exists-1]=textList[counter]
for word in accomodator:
text+=str(word) + " "
print text
test_cases.close()

This code works for me:
import sys
def main(name_file):
_file = open(name_file, 'r')
text = ""
while True:
try:
line = _file.next()
disordered_line, numbers_string = line.split(';')
numbers_list = map(int, numbers_string.strip().split(' '))
missing_number = sum(xrange(sorted(numbers_list)[0],sorted(numbers_list)[-1]+1)) - sum(numbers_list)
if missing_number == 0:
missing_number = len(disordered_line)
numbers_list.append(missing_number)
disordered_list = disordered_line.split(' ')
string_position = zip(disordered_list, numbers_list)
ordered = sorted(string_position, key = lambda x: x[1])
text += " ".join([x[0] for x in ordered])
text += "\n"
except StopIteration:
break
_file.close()
print text.strip()
if __name__ == '__main__':
main(sys.argv[1])
I'll try to explain my code step by step so maybe you can see the difference between your code and mine one:
while True
A loop that breaks when there are no more lines.
try:
I put the code inside a try and catch the StopIteracion exception, because this is raised when there are no more items in a generator.
line = _file.next()
Use a generator, so that way you do not put all the lines in memory from once.
disordered_line, numbers_string = line.split(';')
Get the unordered phrase and the numbers of every string's position.
numbers_list = map(int, numbers_string.strip().split(' '))
Convert every number from string to int
missing_number = sum(xrange(sorted(numbers_list)[0],sorted(numbers_list)[-1]+1)) - sum(numbers_list)
Get the missing number from the serial of numbers, so that missing number is the position of the last string in the phrase.
if missing_number == 0:
missing_number = len(unorder_line)
Check if the missing number is equal to 0 if so then the really missing number is equal to the number of the strings that make the phrase.
numbers_list.append(missing_number)
Append the missing number to the list of numbers.
disordered_list = disordered_line.split(' ')
Conver the disordered phrase into a list.
string_position = zip(disordered_list, numbers_list)
Combine every string with its respective position.
ordered = sorted(string_position, key = lambda x: x[1])
Order the combined list by the position of the string.
text += " ".join([x[0] for x in ordered])
Concatenate the ordered phrase, and the reamining code it's easy to understand.
UPDATE
By looking at your code here is my opinion tha might solve your problem.
split already returns a list so you do not have to loop over the splitted content to add that content to another list.
So these six lines:
for l in test.strip().split(";"):
saver.append(l)
for i in saver[0].split(" "):
textList.append(i)
for j in saver[1].split(" "):
positionList.append(j)
can be converted into three:
splitted_test = test.strip().split(';')
textList = splitted_test[0].split(" ")
positionList = map(int, splitted_test[1].split(" "))
In this line positionList = map(int, splitted_test[0].split(" ")) You already convert numbers into int, so you save these two lines:
for i in range(0,len(positionList)):
positionList[i]=int(positionList[i])
The next lines:
accomodator=[None]*len(textList)
for n in range(1,len(textList)):
if n not in positionList:
accomodator[n]=textList[len(textList)-1]
exists=n
can be converted into the next four:
missing_number = sum(xrange(sorted(positionList)[0],sorted(positionList)[-1]+1)) - sum(positionList)
if missing_number == 0:
missing_number = len(textList)
positionList.append(missing_number)
Basically what these lines do is calculate the missing number in the serie of numbers so the len of the serie is the same as textList.
The next lines:
for item in positionList:
accomodator[item-1]=textList[counter]
counter+=1
if counter>item:
accomodator[exists-1]=textList[counter]
for word in accomodator:
text+=str(word) + " "
Can be replaced by these ones:
string_position = zip(textList, positionList)
ordered = sorted(string_position, key = lambda x: x[1])
text += " ".join([x[0] for x in ordered])
text += "\n"
From this way you can save, lines and memory, also use xrange instead of range.
Maybe the factors that make your code pass partially could be:
Number of lines of the script
Number of time your script takes.
Number of memory your script uses.
What you could do is:
Use Generators. #You save memory
Reduce for's, this way you save lines of code and time.
If you think something could be made it easier, do it.
Do not redo the wheel, if something has been already made it, use it.

Related

How to use a number in the first line of a .txt file to determine the number of words to be printed?

I have this:
from random_word import RandomWords
import time
h = open('/home/rodrigo/Documents/num.txt', 'r')
content = h.readline()
print (content)
a = 0
for line in content:
for i in line:
if i.isdigit() == True:
a += int(i)
r = RandomWords()
key = r.get_random_words()
time.sleep(3)
keys = key[:a]
time.sleep(1)
for key in keys:
print(key)
I'm trying to read and use the number on the first line of a .txt file.
In the .txt file I have just typed the number:
50
However, this code reads only the first digit of the number fifty and the result is that the function print(key) prints only 5 words (it should print 50 words).
If I change the .txt file to the number: 55
The print(key) prints 10 words and not 55 words.
(the function is adding the digits/numeric units of the .txt file)
Can anybody help? How to print an amount of words exactly equal to the number typed in the .txt file?
It reads both digits. But it reads it to a string "50". You then iterate over the digits, convert them to ints and add them up, i.e. int("5") + int("0"). Which gives you 5 (obviously).
So just replace your whole loop with
a = int(content)
if you want to check that file only has digits:
try:
a = int(content)
except ValueError:
print("The content is not intiger")
content is a string, you are iterating through characters in the string in your first for loop (and iterating over the single character string line once with your nested for loop).
If you only need the one line, replacing your first for loop with this should work:
if content.isdigit() == True:
a += int(content)
if you need multiple lines and to add them seperately, add each line to a list like this:
from random_word import RandomWords
import time
h = open('/home/rodrigo/Documents/num.txt', 'r')
content = []
line = h.readline()
while line:
content.append(line)
line = h.readline()
print (content)
a = 0
for line in content: # You only need one for loop.
if line.isdigit() == True:
a += int(i)
r = RandomWords()
key = r.get_random_words()
time.sleep(3)
keys = key[:a]
time.sleep(1)
for key in keys:
print(key)

How to find the largest number of times a word is repeated consecutively in a given string?

Okay, so this is kind of a confusing question, I will try and word it in the best way that I can.
I'm trying to figure out a way that I can find the largest consecutive repeats of a word in a string in Python
For example, let's say the word I want to look for is "apple" and the string is: "applebananaorangeorangeorangebananaappleappleorangeappleappleappleapple". Here, the largest number of consecutive repeats for the word "apple" is 3.
I have tried numerous ways of finding repeating character such as this:
word="100011010" #word = "1"
count=1
length=""
if len(word)>1:
for i in range(1,len(word)):
if word[i-1]==word[i]:
count+=1
else :
length += word[i-1]+" repeats "+str(count)+", "
count=1
length += ("and "+word[i]+" repeats "+str(count))
else:
i=0
length += ("and "+word[i]+" repeats "+str(count))
print (length)
But this works with integers and not words. It also outputs the number of times the character repeats in general but does not identify the largest consecutive repeats. I hope that makes sense. My brain is kind of all over the place rn so I apologize if im trippin
Here is a solution I came up with that I believe solves your problem. There is almost certainly a simpler/faster way to do it if you spend more time with the problem which I would encourage.
import re
search_string = "applebananaorangeorangeorangebananaappleappleorangeappleappleappleapple"
search_term = "apple"
def search_for_term(search_string, search_term):
#split string into array on search_term
#keeps search term in array unlike normal string split
split_string = re.split(f'({search_term})', search_string)
#remove unnecessary characters
split_string = list(filter(lambda x: x != "", split_string))
#enumerate string and filter out instances that aren't the search term
enum_string = list(filter(lambda x: x[1] == search_term, enumerate(split_string)))
#loop through each of the items in the enumerated list and save to the current chain
#once a chain brakes i.e. the next element is not in order append the current_chain to
#the chains list and start over
chains = []
current_chain = []
for idx, val in enum_string:
if len(current_chain) == 0:
current_chain.append(idx)
elif idx == current_chain[-1] + 1:
current_chain.append(idx)
else:
chains.append(current_chain)
current_chain = [idx]
print(chains, current_chain)
#append anything leftover in the current_chain list to the chains list
if len(current_chain) > 0:
chains.append(current_chain)
del current_chain
#find the max length nested list in the chains list and return it
max_length = max(map(len, chains))
return max_length
max_length = search_for_term(search_string, search_term)
print(max_length)
Here is how I would do this. first check for 'apple' in the randString, then check for 'appleapple', then 'appleappleapple', and so on until the search result is empty. Keep track of the iteration count and voilĂ .
randString = "applebananaorangeorangeorangebananaappleappleorangeappleappleappleapple"
find = input('type in word to search for: ')
def consecutive():
count =0
for i in range(len(randString)):
count +=1
seachword = [find*count]
check = [item for item in seachword if item in randString]
if len(check) != 0:
continue
else:
# Need to remove 1 from the final count.
print (find, ":", count -1)
break
consecutive()

How to generate a pyramid of words in python based on a dictionary of words?

I want to generate a pyramid using Python that has the following structure:
The pyramid is built using the following:
The user enters an integer between 1 and 15. Then a "word pyramid" of the requested height is generated. A "word pyramid" is a string of multiple lines, starting with a word of length 1 (first line), followed by a word of length 2(second line), followed by a word of length 3, etc. up to a word with a length that is the height of the pyramid.
Each next word has the same letters as the previous word (though not necessarily in the same order) with one extra letter added.
The pyramid of length 5 looks like so:
a
ad
tad
date
tread
The words are taken from a list of English words (so there are enough words for any given size of the pyramid in order to complete the pyramid).
I have tried the following:
from random import choice
from string import ascii_lowercase
alphabet = ascii_lowercase
def finding(word,target):
chars = []
temp_chars = []
for char in word:
chars.append(char)
for char in target:
temp_chars.append(char)
ok=0
for char in chars:
if temp_chars.count(char) >= 1:
ok += 1
if ok != len(word):
return False
exit()
else:
if len(target) == len(word) +1:
print("For word", target)
return True
exit()
else:
return False
exit()
def game():
outcome = ""
fp = open("wordsEn.txt")
contents = fp.read()
words = contents.split(" ")
user_input = input("Give num from 1 to 15")
num = int(user_input)
if outcome == "" :
my_choice = choice(list(alphabet))
outcome += my_choice + "\n"
line = my_choice
for word in words:
if len(line) > num:
return outcome
exit()
else:
if finding(line,word):
line = word
outcome += line + "\n"
print(game())
The first "finding" function works, and it finds the next word that would fill the next line for the pyramid. I have tried the code for a small list of a few words, and although the outcome string (which is a string that stores the pyramid) had the right form, nevertheless I have the "None" output, both in the small example and in the large example with all the English words.
While we await some more details on the format of the input data, I thought I would come up with a basic solution using the words words_alpha.txt from github.com/dwyl/english-words.
I might produce a few different versions, I'll see if any are clearly superior to the others.
import collections as colls
import operator as op
import random
words_dict = colls.defaultdict(list)
with open('../resources/words_alpha.txt') as words_file:
for line in words_file:
line_clean = line.strip()
words_dict[len(line_clean)].append(line_clean)
# Python 3.7+, dictionaries are in insertion order.
words_list = list(words_dict.values())
pyramid_len = int(input("Enter the size of the pyramid: "))
for curr_words in words_list[:pyramid_len]:
print(random.choice(curr_words))

How to extract all the numbers from a text file using re.findall() and compute the sum using a for-loop?

The basic outline of this problem is to read the file, look for integers using the re.findall(), looking for regular expression of [0-9]+ and then converting the extracted strings to integers and summing up the integers. I'm having different outcome it supposed to end with (209). Also, how can I simplify my code? Thanks (here is the txt file http://py4e-data.dr-chuck.net/regex_sum_167791.txt)
import re
hand = open("regex_sum_167791.txt")
total = 0
count = 0
for line in hand:
count = count+1
line = line.rstrip()
x = re.findall("[0-9]+", line)
if len(x)!= 1 : continue
num = int(x[0])
total = num + total
print(total)
Assuming that you need to sum all the numbers in your txt:
total = 0
with open("regex_sum_167791.txt") as f:
for line in f:
total += sum(map(int, re.findall("\d+", line)))
print(total)
# 417209
Logics
To start with, try using with when you do open so that once any job is done, open is closed.
Following lines are removed as they seemed redundant:
count = count+1: Not used.
line = line.rstrip(): re.findall takes care of extraction, so you don't have to worry about stripping lines.
if len(x)!= 1 : continue: Seems like you wanted to skip the line with no digits. But since sum(map(int, re.findall("\d+", line))) returns zero in such case, this is also unnecessary.
num = int(x[0]): Finally, this effectively grabs only one digit from the line. In case of two or more digits found in a single line, this won't serve the original purpose. And since int cannot be directly applied to iterables, I used map(int, ...).
You were almost there:
import re
hand = open("regex_sum_167791.txt")
total = 0
for line in hand:
count = count+1
line = line.rstrip()
x = re.findall("[0-9]+", line)
for i in x:
total += int(i)
print(total)
Answer: 417209

finding duplicates in a string at python 3

def find_duplicate():
x =input("Enter a word = ")
for char in x :
counts=x.count(char)
while counts > 1:
return print(char,counts)
I've got small problem in there i want to find all duplicates in string but this program give me only one duplicate ex: aassdd is my input function gave me only a : 2 but it need to be in that form a : 2 s : 2 d : 2 thanks for your answers.
return is a keyword that works more or less as immediately exit this function (and optionally carry some output with you). You thus need to remove the return statement:
def find_duplicate():
x =input("Enter a word = ")
for char in x :
counts=x.count(char)
print(char,counts)
Furthermore you also have to remove the while loop (or update the counter if you want to print multiple times), otherwise you will get stuck in an infinite loop since count is not updated and the test will thus always succeed.
Mind however that in this case a will be printed multiple times (in this case two) if it is found multiple times in the string. You can solve this issue by first constructing a set of the characters in the string and iterate over this set:
def find_duplicate():
x =input("Enter a word = ")
for char in set(x):
counts=x.count(char)
print(char,counts)
Finally it is better to make a separation between functions that calculate and functions that do I/O (for instance print). So you better make a function that returns a dictionary with the counts, and one that prints that dictionary. You can generate a dictionary like:
def find_duplicate(x):
result = {}
for char in set(x):
result[char]=x.count(char)
return result
And a calling function:
def do_find_duplicates(x):
x =input("Enter a word = ")
for key,val in find_duplicate(x).items():
print(key,val)
And now the best part is: you actually do not need to write the find_duplicate function: there is a utility class for that: Counter:
from collections import Counter
def do_find_duplicates(x):
x =input("Enter a word = ")
for key,val in Counter(x).items():
print(key,val)
This will help you.
def find_duplicate():
x = input("Enter a word = ")
for char in set(x):
counts = x.count(char)
while counts > 1:
print(char, ":", counts, end=' ')
break
find_duplicate()
Just because this is fun, a solution that leverages the built-ins to avoid writing any more custom code than absolutely needed:
from collections import Counter, OrderedDict
# To let you count characters while preserving order of first appearance
class OrderedCounter(Counter, OrderedDict): pass
def find_duplicate(word):
return [(ch, cnt) for ch, cnt in OrderedCounter(word).items() if cnt > 1]
It's likely more efficient (it doesn't recount each character over and over), only reports each character once, and uses arguments and return values instead of input and print, so it's more versatile (your main method can prompt for input and print output if it chooses).
Usage is simple (and thanks to OrderedCounter, it preserves order of first appearance in the original string too):
>>> find_duplicate('aaacfdedbfrf')
[('a', 3), ('f', 3), ('d', 2)]
def find_duplicate():
x = input("Enter a word = ")
dup_letters = []
dup_num = []
for char in x:
if char not in dup_letters and x.count(char) > 1:
dup_letters.append(char)
dup_num.append(x.count(char))
return zip(dup_letters, dup_num)
dup = find_duplicate()
for i in dup:
print(i)
This version should be fast as I am not using any library or more than one cycle, do you have any faster options?
import datetime
start_time = datetime.datetime.now()
some_string = 'Laptop' * 99999
ans_dict = {}
for i in some_string:
if i in ans_dict:
ans_dict[i] += 1
else:
ans_dict[i] = 1
print(ans_dict)
end_time = datetime.datetime.now()
print(end_time - start_time)
def find_duplicate():
x = input("Enter a word = ")
y = ""
check = ""
for char in x:
if x.count(char) > 1 and char not in y and char != check:
y += (char + ":" + str(x.count(char)) + " ")
check = char
return y.strip()

Categories