The question for the code is 'input a word and check whether the first character of the word is repeated in the word again or not. If yes then change all the repeating characters to $ except the first character.'
So I coded the following and used the logic to start the loop from the second character of the word so that first character remains unchanged.
a=input()
for i in range(1,len(a)):
if(a[i]==a[0]):
b=a.replace(a[i],'$')
print(b)
for the above program I gave the input as 'agra' and to my surprise got the output as '$gr$'. the first character was also changed.
What is the problem with my logic? and what other solution do you suggest?
That is more simply done like:
Code:
b = a[0] + a[1:].replace(a[0], '$')
Test Code:
a = 'stops'
b = a[0] + a[1:].replace(a[0], '$')
print(b)
Results:
stop$
For the correct solution in python, see Stephen Rauch's answer.
I think that what you where trying to achieve, in a very "unpythonic" way, is:
a = input()
b = a # b is a copy
for i in range(1, len(a)):
if a[i] == a[0]:
# replace i-th char of b by '$''
print (b)
How to do that replacement? In python: strings are immutable, that means you cannot replace a char "in place". Try to do this:
a='agra'
a[3] = '$'
And you'll get an error:
TypeError: 'str' object does not support item assignment
If you want to replace the i-th char of a string by $, you have to write:
b = b[:i] + '$' + b[i+1:]
That is: build a new string from b[0], ..., b[i-1], add a $ and continue with b[i+1], ..., b[len(a)-1]. If you use this in your code, you get:
a = input()
b = a
for i in range(1, len(a)):
if a[i] == a[0]:
b = b[:i] + '$' + b[i+1:]
print (b)
Okay, it works but don't do that because it's very "unpythonic" and inefficient.
BEGIN EDIT
By the way, you don't need to replace, you can just build the string character by character:
a = input()
b = a[0] # start with first char
for i in range(1, len(a)):
if a[i] == a[0]:
b += '$' # $ if equals to first char
else:
b += a[i] # else the current char
print (b)
END EDIT
That gave me this idea:
a=input()
b="".join('$' if i!=0 and c==a[0] else c for i,c in enumerate(a))
print(b)
Explanation: the list comprehension takes all characters of a along with their position i (that's what enumerate does). For every couple position, character, if the position is not 0 (not the first character) and if the character is equal to a[0], then put a $. Else put the character itself. Glue everything together to make a new string.
Again, that's not the right way to do what you are trying to do, because there is another way that is neater and easier (see Stephen Rauch's answer), but is shows how you can sometimes handle difficulties in python.
a=input()
for i in range(1,len(a)):
if(a[i]==a[0]):
b=a[1:len(a)].replace(a[i],'$')
print(a[0]+b)
you changed whole word/sentence 'a': a.replace(...)
Related
How can I write this code in one line? The concept is that you should:
get one input from the user and check if the (ASCII form of the character) - 97 is divisible by 2 or not
if yes, you should print the original form of the character
else, you should print the upper case form of the character.
last, you should reverse the answer.
Example, if the input is alexander, the output should be e e a a X R N L D
But it should be in one line and only one, I came up with a solution but it was 3 lines, I don't know what to do next.
This is the code I came up with so far:
h = []
for i in input() : h.append(i.lower() if (ord(i) - 97) % 2 == 0 else i.upper())
print(*sorted(h, reverse=True))
The original code for the question, which you should convert to one line is:
input_string = str(input())
array = []
for i in range(len(input_string)):
if (ord(input_string[i]) - 97) % 2 == 0:
array.append(input_string[i])
else:
array.append(input_string[i].upper())
array.sort(reverse=True)
answer = ' '.join(array)
print(answer)
List comprehension (I did not check your code, only rewrite it):
h = []
for i in input() : h.append(i.lower() if (ord(i) - 97) % 2 == 0 else i.upper())
print(*sorted(h, reverse=True))
print(*sorted([i.lower() if (ord(i)-97)%2 == 0 else i.upper() for i in input() ], reverse=True))
To quote your question:
you should print the original form of the character
That is not what the code does at the moment, just saying so you are aware.
after reading your deleted comment:
And if you are wondering about the if and else in list comprehension:
You can put it in your list, but if that was your problem (the actual question apparently) then I would suggest to use google, there are plenty of examples where this is used.: if/else in a list comprehension, https://towardsdatascience.com/a-gentle-introduction-to-flow-control-loops-and-list-comprehensions-for-beginners-3dbaabd7cd8a, https://pythonguides.com/python-list-comprehension-using-if-else/
I am trying to understand a open source code from the following link:
https://github.com/alexbaucom17/DominoRobot/blob/master/src/tools/plot_logs.py
Can anybody explain what exactly happening in the line: if c in ['[',']',',','\n']:
def get_value(line, path):
idx = 0
for p in path:
idx = line.find(p, idx)
idx += len(p)
data = ""
for c in line[idx:]:
if c in ['[',']',',','\n']:
break
elif c in [':',' ']:
continue
else:
data += c
return float(data)
The in operator checks for containment. So it is literally checking if the length-1 string c is one of the elements [],\n. If so, it ends the loop using break if not, it checks against : . Because of how containment checks work, and the fact that c is guaranteed by the loop to be a single character, you can implement the check like this:
if c in '[],\n':
break
elif c in ': ':
continue
else:
data += c
While we're here, data += c is not a great way to accumulate strings, since they are immutable. You may be better off appending to a list instead:
data = []
for c in line[idx:]:
...
data = ''.join(data)
Better yet, record the index of the first element you find, slice the original, and remove the two undesirable characters:
for i, c in line[idx:]:
if c in '[],\n':
break
data = line[idx:i].replace(':', '').replace(' ', '')
This code is not written to be read easily.
It would be better if it included some spaces to make it more clear:
if c in ['[', ']', ',', '\n']:
['[', ']', ',', '\n'] is a list of four single-character string literals:
'['
']'
','
'\n' (the line break character)
This line tests if c is contained in the list, i.e., if it is equal to any of those four characters.
What can be even more confusing is that [, ], and , appear both as one of the four characters to be tested, and as part of the list syntax [x, y, z].
It is set to true if c has one of the values in the list, so if it is one of those characters.
It is the same as checking if c is equal to each item from the list, and if it is equal to any of them, it returns true.
the output if given a string, "abcdefg" of length 7 as example, should print out 7 lines like:
abcdefg
bcdefga
cdefgab
defgabc
efgabcd
fgabcde
gabcedf
but I seem to be missing the boat after many many hours of various loops and print statements
s = str("abcdefg")
print(s)
print()
for i in range(len(s)):
new_s = s[:i+1] + s[-i:] + s[-i]
print(new_s)
I get this:
abcdefg
aabcdefga
abgg
abcfgf
abcdefge
abcdedefgd
abcdefcdefgc
abcdefgbcdefgb
You're overcomplicating this. The proper expression is just
new_s = s[i:] + s[:i]
slicing is inclusive of the start index, and exclusive of the end index. This above expression guarantees to keep the length of the result the same as the input list, just swapping variable parts of it.
Note that the first new_s value is the original string itself. No need to print it at the start of the program.
The result is:
abcdefg
bcdefga
cdefgab
defgabc
efgabcd
fgabcde
gabcdef
slicing in detail: Understanding slice notation
the loop could be like:
s_len = len(s)
for i in range(s_len):
s = s[1:] + s[0]
print(s)
This is the problem definition:
Given a string of lowercase letters, determine the index of the
character whose removal will make a palindrome. If is already a
palindrome or no such character exists, then print -1. There will always
be a valid solution, and any correct answer is acceptable. For
example, if "bcbc", we can either remove 'b' at index or 'c' at index.
I tried this code:
# !/bin/python
import sys
def palindromeIndex(s):
# Complete this function
length = len(s)
index = 0
while index != length:
string = list(s)
del string[index]
if string == list(reversed(string)):
return index
index += 1
return -1
q = int(raw_input().strip())
for a0 in xrange(q):
s = raw_input().strip()
result = palindromeIndex(s)
print(result)
This code works for the smaller values. But taken hell lot of time for the larger inputs.
Here is the sample: Link to sample
the above one is the bigger sample which is to be decoded. But at the solution must run for the following input:
Input (stdin)
3
aaab
baa
aaa
Expected Output
3
0
-1
How to optimize the solution?
Here is a code that is optimized for the very task
def palindrome_index(s):
# Complete this function
rev = s[::-1]
if rev == s:
return -1
for i, (a, b) in enumerate(zip(s, rev)):
if a != b:
candidate = s[:i] + s[i + 1:]
if candidate == candidate[::-1]:
return i
else:
return len(s) - i - 1
First we calculate the reverse of the string. If rev equals the original, it was a palindrome to begin with. Then we iterate the characters at the both ends, keeping tab on the index as well:
for i, (a, b) in enumerate(zip(s, rev)):
a will hold the current character from the beginning of the string and b from the end. i will hold the index from the beginning of the string. If at any point a != b then it means that either a or b must be removed. Since there is always a solution, and it is always one character, we test if the removal of a results in a palindrome. If it does, we return the index of a, which is i. If it doesn't, then by necessity, the removal of b must result in a palindrome, therefore we return its index, counting from the end.
There is no need to convert the string to a list, as you can compare strings. This will remove a computation that is called a lot thus speeding up the process. To reverse a string, all you need to do is used slicing:
>>> s = "abcdef"
>>> s[::-1]
'fedcba'
So using this, you can re-write your function to:
def palindromeIndex(s):
if s == s[::-1]:
return -1
for i in range(len(s)):
c = s[:i] + s[i+1:]
if c == c[::-1]:
return i
return -1
and the tests from your question:
>>> palindromeIndex("aaab")
3
>>> palindromeIndex("baa")
0
>>> palindromeIndex("aaa")
-1
and for the first one in the link that you gave, the result was:
16722
which computed in about 900ms compared to your original function which took 17000ms but still gave the same result. So it is clear that this function is a drastic improvement. :)
I just starting to learn Python and have been following the Google Python class. In one of the string exercises, there is this code:
def not_bad(s):
n = s.find('not')
b = s.find('bad')
if n != -1 and b != -1 and b > n:
s = s[:n] + 'good' + s[b+3:]
return s
I was wondering what the s[b+3:] stands for, as it is the first time I have come across the + within a string slice.
+ is just the addition operator, which adds the value of b with 3. It is used in this case, to skip the three characters bad.
s[:n] keeps all the characters till not, + 'good' +, s[b+3:] all the characters after bad.
It's just another expression. s[b+3:], equivalent to s[(b+3):], means the portion of s starting three characters from the position b.