pythonic way to convert character position to terminal offset as printed - python-3.x

I am wondering if there is a "pythonic" way to from the a character position in a string to the terminal offset that character will be printed at (i.e including tabs).
For example take the following three strings:
$> python3
>>> print("+\tabc")
+ abc
>>> print("\tabc")
abc
>>> print(" abc")
abc
They are three difference strings, with three different character counts preceding the "abc", but the position of 'a' is different each time.
The only solution I have that works "well enough" is
def get_offset(s, c):
pos = s.find(c)
if pos == -1:
return -1
tablen = 0
ntabs = 0
for i in range(0, pos):
if line[i] == '\t':
tablen += (TABLEN - (i % TABLEN))
ntabs += 1
offset = tablen + (pos - ntabs)
return offset
I am wondering is there a more pythonic way to do this?

Not really.
Because python doesn't know about how its output will be rendered, it cannot tell you the offset resulting from tab characters. From python's point of view, a tab is a character like any other.

Related

How do I write a python function to count consecutive zeros in a binary representation of a number?

Given a number N, the function should convert the number to binary form, count the number of consecutive zero (the binary gap), and return the maximum binary gap. For example, 9 = 1001, the binary gap of length 2. The number 529 = 1000010001, has 2 binary gaps with length 4 and 3. If the number has 2 or more binary gaps, the function should return the maximum binary gap i.e. 4 in the case of N = 529.
I tried this function:
def solution(N):
binaryN = bin(N)[2:]
n = len(binaryN)
binaryGap = []
for i in range(n):
if binaryN[i] == 0 and binaryN[i + 1] == 0:
m = len(binaryN)
else:
return 0
binaryGap = binaryGap.append(m)
return max(binaryGap)
The function returns 0 for all values of N which is incorrect. How do I debug/improve the code to produce the accurate result?
Check out the below code. It would solve your problem.
The code is self-explanatory, yet let me know in-case of any doubts.
The Code:
import sys
num = int(sys.argv[1])
# Function to get the binary gap.
def binaryGapFinder(num):
binnum = bin(num).replace("0b", "") # binnum is binary form of the given number.
i = 0
x = 0
x_list = []
while i <= len(binnum)-1:
if binnum[i] == "0":
x += 1
if i == len(binnum)-1: # This loop will also consider if binary form is ending with 0. for example: 12 -> 1100
x_list.append(x)
else:
x_list.append(x)
x = 0
i += 1
return f"The Number: {num}\nIt's Binary Form: {binnum}\nMaximum Consecutive 0's: {max(x_list)}"
print(binaryGapFinder(num))
The Output:
python3 /the/path/to/your/script/binarygap.py 529
The Number: 529
It's Binary Form: 1000010001
Maximum Consecutive 0's: 4
python3 /the/path/to/your/script/binarygap.py 12
The Number: 12
It's Binary Form: 1100
Maximum Consecutive 0's: 2
python3 /the/path/to/your/script/binarygap.py 512
The Number: 512
It's Binary Form: 1000000000
Maximum Consecutive 0's: 9
There's a few issues here worth mentioning to aid you. (Just a side note to start with is that, in Python, it's recommended/best practice to use all lower case for variable names, so I'll replace them in my examples below.)
The bin() built in function returns a string. So you should be checking for equality with "0" (or '0') instead of an integer. e.g.
if binaryN[i] == "0" and binaryN[i + 1] == "0":
With Python you don't need to bother with checking for lengths of strings (or any other iterables) to use in a for loop in scenarios like this. e.g. You can replace:
n = len(binaryN)
for i in range(n):
with the more "Pythonic" way:
for bit in binary_number:
You can then use the variable bit (call it whatever you want of course, bearing in mind that good variable names make code more readable) instead of binary_number[index]. In this case, with each iteration of the for loop, bit will be replaced with the next character in the binary_number string.
From there on in your code:
m = len(binaryN)
will always be the same value, which is the total length of the string binaryN. e.g. 4 for '1001'.) This is not what you intended.
The first statement in your else block of code return 0 will terminate your function immediately and return 0 and thus your binaryGap = binaryGap.append(m) code will never, ever execute as it's unreachable due to that preceding return stopping any further execution of code in that suite.
You've got the right idea(s) and heading towards the right track for a solution but I don't think your code, even when the issues above are corrected, will match all possible binary numbers you may encounter. So, another possible alternative (and yet roughly sticking with the solution I think that you had in mind yourself) would be something like this which I hope will help you:
def solution(n):
binary_no = bin(n)[2:]
binary_gaps = []
gap_counter = 0
for bit in binary_no:
if bit == "0":
gap_counter += 1
else:
# Encountered a 1 so add current count of 0's -- if any -- to list and reset gap_counter
if gap_counter > 0:
binary_gaps.append(gap_counter)
gap_counter = 0
else:
# A for else suite (block of code) is run when all iterables have been exhausted.
if gap_counter > 0:
binary_gaps.append(gap_counter)
if binary_gaps: # If there is at least one element in the list
if len(binary_gaps) > 1:
return max(binary_gaps)
else:
return binary_gaps[0]
else:
# The list is empty, so no gaps were found at all. i.e. Binary number was all 1's.
return 0
print(solution(529))

return outside the function

there is a syntax error that says that i am returning outside the function
I tried all the possible solutions that people used on the same problem with there code and i still get the same error
the error is in line 32 in the line return result
Problem Introduction
In this problem, we ask a simple question: how many times one string occurs as a substring of another? Recall that di erent occurrences of a substring can overlap with each other. For example, ATA occurs three times in CGATATATCCATAG.
Problem Description
Task. Find all occurrences of a pattern in a string.
Input Format. Strings π‘ƒπ‘Žπ‘‘π‘‘π‘’π‘Ÿπ‘› and πΊπ‘’π‘›π‘œπ‘šπ‘’.
Constraints. 1 ≀ |π‘ƒπ‘Žπ‘‘π‘‘π‘’π‘Ÿπ‘›| ≀ 106; 1 ≀ |πΊπ‘’π‘›π‘œπ‘šπ‘’| ≀ 106; both strings are over A, C, G, T.
Sample 1.
Input:
Output:
1 12
4 1.5 2
4 4 24
TACG GT
Explanation:
The pattern is longer than the text and hence has no occurrences in the text.
Sample 2.
Input:
Output:
02
Explanation:
The pattern appears at positions 1 and 3 (and these two occurrences overlap each other).
Sample 3.
Input:
Output:
139
Explanation:
The pattern appears at positions 1, 3, and 9 in the text.
ATA ATATA
ATAT
GATATATGCATATACTT
# python3
import sys
def compute_prefix_function(pattern):
s = [0] * len(pattern)
border = 0
for i in range(1, len(pattern)):
while (border > 0) and (pattern[i] != pattern[border]):
border = s[border - 1]
if pattern[i] == pattern[border]:
border = border + 1
else:
border = 0
s[i] = border
return s
def find_pattern(pattern, text):
S = pattern + '$' + text
s = compute_prefix_function(S)
result = []
p = len(pattern)
for i in range(p + 1, len(S)):
if s[i] == p:
result.append(i - 2 * p)
return result
if __name__ == '__main__':
pattern = sys.stdin.readline().strip()
text = sys.stdin.readline().strip()
result = find_pattern(pattern, text)
print(" ".join(map(str, result)))
Realize that white space/indentation matters in python, and replaces the { }, used in most other language to define a scope. Something like this is a proper function (although, the return isn't really necessary):
def foo():
print("bar")
return
Doing this instead would result in an error message similar to your, though, because the return now is outside the scope of the function:
def foo():
print("bar")
return
For more info just Google for python indentation tutorial.

Lexicographically smallest palindrome in python

I found this question to be interesting and I would like to share this here and find reasonably good codes, specific to py :
Given a string S having characters from English alphabets ['a' - 'z'] and '.' as the special character (without quotes).
Write a program to construct the lexicographically smallest palindrome by filling each of the faded character ('.') with a lower case alphabet.
Definition:
The smallest lexicographical order is an order relation where string s is smaller than t, given the first character of s (s1 ) is smaller than the first character of t (t1 ), or in case they
are equivalent, the second character, etc.
For example : "aaabbb" is smaller than "aaac" because although the first three characters
are equal, the fourth character b is smaller than the fourth character c.
Input Format:
String S
Output Format:
Print lexicographically smallest palindrome after filling each '.' character, if it
possible to construct one. Print -1 otherwise.
Example-1
Input:
a.ba
Output:
abba
Example-2:
Input:
a.b
Output:
-1
Explanation:
In example 1, you can create a palindrome by filling the '.' character by 'b'.
In example 2, it is not possible to make the string s a palindrome.
You can't just copy paste questions from NPTEL assignments and ask them here without even trying!
Anyways,since the "code" is your only concern,try copy pasting the lines below:
word = input()
length = len(word)
def SmallestPalindrome(word, length):
i = 0
j = length - 1
word = list(word) #creating a list from the input word
while (i <= j):
if (word[i] == word[j] == '.'):
word[i] = word[j] = 'a'
elif word[i] != word[j]:
if (word[i] == '.'):
word[i] = word[j]
elif (word[j] == '.'):
word[j] = word[i]
else: # worst case situation when palindrome condition is not met
return -1
i = i + 1
j = j - 1
return "".join(word) # to turn the list back to a string
print(SmallestPalindrome(word, length)) #Print the output of your function
s=input()
s=list(s)
n=len(s)
j=n
c=0
for i in range(n):
j=j-1
if((s[i]==s[j]) and (i==j) and (s[i]=='.' and s[j]=='.')):
s[i]='a'
s[j]='a'
elif(s[i]==s[j]):
continue
elif((s[i]!=s[j]) and (i!=j) and (s[i]=='.' or s[j]=='.')):
if(s[i]!='.'):
s[j]=s[i]
else:
s[i]=s[j]
elif((i==j) and (s[i]=='.')):
s[i]=a
else:
c=c+1
break
if(c<1):
for k in s:
print(k,end="")
else:print("-1")

Circular Walk in a string

You are given a string in which 'A' means you can move 1 step clockwise, 'C' means you can move one step anticlockwise and '?' means you can move one step either clockwise or anti clockwise. So Given a string find maximum distance from inital position at any given point of time.
for eg:-
input : - AACC?CC
output :- 3
explanation : - if ? is replaced with C then max distance will become 3
optimal approach to solve this problem?
str = "AACC?CC"
count = 0
extra = 0
for i in str:
if i == 'A':
count -= 1
elif i == 'C':
count += 1
else:
extra += 1
dist = abs(count) + extra
if count < 0:
print "AntiClockwise:",
else:
print "ClockWise:",
print dist
Just try this out. however 'A', 'C' movements must be taken place, so you should go left and right. the '?'is optional. You can just count How many '?' are there and add it to the final answer.

Count 2 (or more) characters recursively in string; return in (x,y) format in Python

I have written a program that will count how many ' ' single spaces or h characters in a string you enter when you call the function:
def chars(s):
if not s:
return 0
else:
return (s[0] == 'h') + chars(s[1:])
When you call chars('hello how are you here')
You will get 3.
Now, let's say I want to count the e along with the h. The h will return a 3 and the e should return a 4. Output would be (3,4).
I tried def chars(s, j=0)and set a counter but then realized, hold on, this has no connection to anything at this point deeming it pointless. I guess, how would I define what that second variable is? Because I only want 1 string as an input.
I am completely lost on how to include that second variable.
Also, just throwing it out there, would I follow the same rules as for 2 characters for more characters? Or would there be a different way?
This is what you want:
def count(s):
if not s:
return (0, 0)
else:
next_count = count(s[1:])
return ((s[0] == 'h') + next_count[0],
(s[0] == 'e') + next_count[1])
count("hello how are you here") # => (3, 4)
The base case returns the tuple (0, 0) and the recursive step looks at both of the values of the next count and adds one to each if necessary.
If you want more than 2 characters, just make the tuples bigger (probably using loops).

Resources