How to get lines count in string? - string

On the whole, I get a string from JSON pair which contain "\n" symbols. For example,
"I can see how the earth nurtures its grass,\nSeparating fine grains from lumpy earth,\nPiercing itself with its own remains\nEnduring the crawling insects on its surface.\nI can see how like a green wave\nIt lifts the soil, swelling it up,\nAnd how the roots penetrate the surrounding mulch\nHappily inhaling the air in the sky.\nI can see how the light illuminates the flowers, -\nPouring itself into their tight buds!\nThe earth and the grass – continue to grow!\nDrowning the mountains in a sea of green...\nOh, The power of motion of the young,\nThe muscular pull of the plants!\nOpening up to the planet, the sun and to you,\nBreaking through the undergrowth to the fresh spring air!"
This string is a poetry for some picture.
Now I need to resize my display.newText object according to text length.
Here is how I see to do that:
Get number of lines (number of "\n" + 1, because where is no "\n" in the end)
In for loop get the longest line
Set display.newText object's size. May be using fontSize for calculating coefficient...
Question is: How to get number of lines?

To get the number of '\n' in a string, you can use string.gsub, it's used for string substitution, but it also returns the number of matches as the second return value.
local count = select(2, str:gsub('\n', '\n'))
or similar:
local _, count = str:gsub('\n', '\n')

This is apparently way faster than #Yu Hao's two solutions
local function get_line_count(str)
local lines = 1
for i = 1, #str do
local c = str:sub(i, i)
if c == '\n' then lines = lines + 1 end
end
return lines
end

Related

Problem when printing output in Python (with easyinput)

So I'm having trouble with enters and line breaks in my code. I must use easyinput library (and import read).
My code stands for:
Input: Input consists of several cases separated by an empty line. Every case has three parts ('lines'). The first one is a line with the translation table: 26 different characters (with no spaces nor ‘_’), the first one corresponding to ‘a’, the second one to ‘b’, …, and the last one to ‘z’. The second part is a number n > 0 in a line. The third part consists of n encrypted lines of text.
Output: For each case, write the original text, also with n lines. Change each ‘_’ of the encrypted text for a space. Write an empty line at the end of each case.
So I figured out how to solve the problem, the things is that my code prints 'well' entering line by line in input. But the problem input must be entered the whole entire. I put an example for better understanding:
Some input should be:
52-!813467/09*+.[();?`]<:>
6
5_3++!_305))_6*_;48_26)4+.)_4+);80_6*_;48_!8`60)_)85;
;]8*;:_+*8_!83(88)_5*!_;46(;88*_96*?;8)
*+(;485);_5*!_2:_*+(;4
956*_2(5*-4_)8`8*;4_0692_85);_)6!8
)4++;_1(+9_;48_081;_8:8_+1_;48_!85;4)_485!
5_288_06*8_1(+9_;48_;(88_;4(+?34_;48_)4+;_161;:_188;_+?;
bcdefghijklmnopqrstuvwxyza
3
cfxbsf_pg_cvht_jo_uif_bcpwf_dpef
j_ibwf_pomz_qspwfe_ju_dpssfdu
opu_usjfe_ju
And its output must be:
a good glass in the bishops hostel in the devils seat
twenty one degrees and thirteen minutes
northeast and by north
main branch seventh limb east side
shoot from the left eye of the deaths head
a bee line from the tree through the shot fifty feet out
beware of bugs in the above code
i have only proved it correct
not tried it
My code far now is:
from easyinput import read
abc = 'abcdefghijklmnopqrstuvwxyz'
values = [letter for letter in abc]
old_abc = read(str)
while old_abc is not None:
keys = [old_letter for old_letter in old_abc]
dict_abc = dict(zip(keys, values))
num_lines = read(int)
for i in range(num_lines):
line = read(str)
for j in line:
if j == '_':
print(' ', end = '')
else:
print(dict_abc[str(j)], end = '')
print('\n')
old_abc = read(str)
I do not find a way of making my code easier, I just want some help to finally print the desired output. Thanks

Keeping the same distance no matter the string length [duplicate]

I'm sure this is covered in plenty of places, but I don't know the exact name of the action I'm trying to do so I can't really look it up. I've been reading an official Python book for 30 minutes trying to find out how to do this.
Problem: I need to put a string in a certain length "field".
For example, if the name field was 15 characters long, and my name was John, I would get "John" followed by 11 spaces to create the 15 character field.
I need this to work for any string put in for the variable "name".
I know it will likely be some form of formatting, but I can't find the exact way to do this. Help would be appreciated.
This is super simple with format:
>>> a = "John"
>>> "{:<15}".format(a)
'John '
You can use the ljust method on strings.
>>> name = 'John'
>>> name.ljust(15)
'John '
Note that if the name is longer than 15 characters, ljust won't truncate it. If you want to end up with exactly 15 characters, you can slice the resulting string:
>>> name.ljust(15)[:15]
If you have python version 3.6 or higher you can use f strings
>>> string = "John"
>>> f"{string:<15}"
'John '
Or if you'd like it to the left
>>> f"{string:>15}"
' John'
Centered
>>> f"{string:^15}"
' John '
For more variations, feel free to check out the docs: https://docs.python.org/3/library/string.html#format-string-syntax
You can use rjust and ljust functions to add specific characters before or after a string to reach a specific length.
The first parameter those methods is the total character number after transforming the string.
Right justified (add to the left)
numStr = '69'
numStr = numStr.rjust(5, '*')
The result is ***69
Left justified (add to the right)
And for the left:
numStr = '69'
numStr = numStr.ljust(3, '#')
The result will be 69#
Fill with Leading Zeros
Also to add zeros you can simply use:
numstr.zfill(8)
Which gives you 00000069 as the result.
string = ""
name = raw_input() #The value at the field
length = input() #the length of the field
string += name
string += " "*(length-len(name)) # Add extra spaces
This will add the number of spaces needed, provided the field has length >= the length of the name provided
name = "John" // your variable
result = (name+" ")[:15] # this adds 15 spaces to the "name"
# but cuts it at 15 characters
I know this is a bit of an old question, but I've ended up making my own little class for it.
Might be useful to someone so I'll stick it up. I used a class variable, which is inherently persistent, to ensure sufficient whitespace was added to clear any old lines. See below:
2021-03-02 update: Improved a bit - when working through a large codebase, you know whether the line you are writing is one you care about or not, but you don't know what was previously written to the console and whether you want to retain it.
This update takes care of that, a class variable you update when writing to the console keeps track of whether the line you are currently writing is one you want to keep, or allow overwriting later on.
class consolePrinter():
'''
Class to write to the console
Objective is to make it easy to write to console, with user able to
overwrite previous line (or not)
'''
# -------------------------------------------------------------------------
#Class variables
stringLen = 0
overwriteLine = False
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def writeline(stringIn, overwriteThisLine=False):
import sys
#Get length of stringIn and update stringLen if needed
if len(stringIn) > consolePrinter.stringLen:
consolePrinter.stringLen = len(stringIn)+1
ctrlString = "{:<"+str(consolePrinter.stringLen)+"}"
prevOverwriteLine = consolePrinter.overwriteLine
if prevOverwriteLine:
#Previous line entry can be overwritten, so do so
sys.stdout.write("\r" + ctrlString.format(stringIn))
else:
#Previous line entry cannot be overwritten, take a new line
sys.stdout.write("\n" + stringIn)
sys.stdout.flush()
#Update the class variable for prevOverwriteLine
consolePrinter.overwriteLine = overwriteThisLine
return
Which then is called via:
consolePrinter.writeline("text here", True)
If you want this line to be overwriteable
consolePrinter.writeline("text here",False)
if you don't.
Note, for it to work right, all messages pushed to the console would need to be through consolePrinter.writeline.
I generally recommend the f-string/format version, but sometimes you have a tuple, need, or want to use printf-style instead. I did this time and decided to use this:
>>> res = (1280, 720)
>>> '%04sx%04s' % res
'1280x 720'
Thought it was a touch more readable than the format version:
>>> f'{res[0]:>4}x{res[1]:>4}'
First check to see if the string's length needs to be shortened, then add spaces until it is as long as the field length.
fieldLength = 15
string1 = string1[0:15] # If it needs to be shortened, shorten it
while len(string1) < fieldLength:
rand += " "
Just whipped this up for my problem, it just adds a space until the length of string is more than the min_length you give it.
def format_string(str, min_length):
while len(str) < min_length:
str += " "
return str

How to split a string after a dot UNLESS the characters after the dot are numbers

I need to take only the letters and numbers at the beginning of a string, but some numbers are decimals. The strings are not all formatted the same. Here are a few examples of some of the data and what I would need returned:
HB61 .M16 1973 I need HB61 returned
HB97.52 .R6163 1982 I need HB97.52 returned
HB98.V38 1994 I need HB98 returned
HB 119.G74 A3 2007 I need HB119 returned
I'm very new to coding so I'm hoping there's some simple solution that I just don't know?
I was going to just split it at the first dot and then get rid of the spaces, but this wouldn't allow me to keep the decimals such as HB97.52 which I need. I currently have code written just to test one string at a time. The code is as follows:
data = input("Data: ")
components = data.split(".")
str(components)
print(components[0].replace(" ", ""))
This works as expected except for the strings with decimals. for HB97.52 .R6163 1982 I would like HB97.52 returned but it only returns HB97.
The following regular expression extracts the letters at the beginning of a string, followed by optional spaces, followed by a [possibly floating point] number:
s = ['HB61 .M16 1973', 'HB97.52 .R6163 1982',
'HB98.V38 1994', 'HB 119.G74 A3 2007']
import re
pattern = r"^[a-z]+\s*\d+(?:\.\d+)?"
[re.findall(pattern, part, flags=re.I)[0] for part in s]
#['HB61', 'HB97.52', 'HB98', 'HB 119']
If you do not want the spaces in the output, this slightly different pattern extracts the letter part and the number part separately, and then they are joined:
pattern = r"(^[a-z]+)\s*(\d+(?:\.\d+)?)"
list(map("".join, [re.findall(pattern, part, flags=re.I)[0] for part in s]))
#['HB61', 'HB97.52', 'HB98', 'HB119']
For something like HB61.45.78.R5000 what do you want? If you want HB61.45.78 then use this first snippet:
data = data.replace(' ', '')
data = data.split('.')
wanted = data[0]
for i in range(1,len(data)):
if data[i][0].isalpha():
break
else:
wanted += '.' + data[i]
Otherwise, if you want only HB61.45 then use
data = data.replace(' ', '')
data = data.split('.')
wanted = data[0]
if not data[1][0].isalpha():
wanted += '.' + data[1]

How can I remove POS Tags in pythons and print the tree preserving subtree orders

I am pretty new to python and need help on the following.
I have a string of the format:
(S Silver/RB (Chunk 42/CD inch/NN) LED/NNP HD/NNP Nakamichi/NNP Smart/NNP Flat/NNP (Chunk 3D/CD TV/NN))
The output I want:
Silver , 42 inch, LED , Nakamichi, Smart, Flat , 3D TV
Basically I want to preserve the subtree as a single string while printing it.
Please help
Firstly, you should only post to SO with some code you tried yourself, so we can see you made any effort to solve your own problem. Getting help in state you shown is just a good will of people, but probably your post is gonna just be downvoted.
Anyways, the pattern you've shown here doesn't seem to obey any rule, as, for example, 'Silver' part has the '/RB' string stripped from it and '42 inch' element from output has not only to strip other strings, that are '/CD' and '/NN', but should also be connected as one string. Unless you just messed up your commas and you want a single string (not a list, as it seems with what you have posted), then:
text = '(S Silver/RB (Chunk 42/CD inch/NN) LED/NNP HD/NNP Nakamichi/NNP Smart/NNP Flat/NNP (Chunk 3D/CD TV/NN))'
split_text = text.split(' ')
new_text = ''
for item in split_text:
if item[0].isnumeric():
new_text += item[:item.find('/')] + ' '
elif item[0] == '(':
pass
else:
new_text += item[:item.find('/')] + ' , '
new_text = new_text[:-3]
new_text
Output:
'Silver , 42 inch , LED , HD , Nakamichi , Smart , Flat , 3D TV'
Still there is little point to do that as the string is short and there are no regular patterns in it (unless, as I said, you messed up with showing what you really want).

Lua Carrying over a value through line wrap code

Previously, I received help in the following link:
Lua Line Wrapping excluding certain characters
Short description of the above is that I was looking for a way to be able run a line wrap function while ignoring character count of certain characters.
Now I've come across another issue. I want to be able to carry the last colour code over to the new line. For example:
If this line #Rwere over 79 characters, I would want to #Breturn the last known colour code #Yon the line break.
Running the function I have in mind would result in:
If this line #Rwere over 79 characters, I would want to #Breturn the last known
#Bcolour code #Yon the line break.
instead of
If this line #Rwere over 79 characters, I would want to #Breturn the last known
colour code #Yon the line break.
I wish for it to do so because in many cases, the MUD will default back to the #w colour code, so it would make colourizing text rather difficult.
I've figured the easiest way to do that would be a reverse match, so I've written a reverse_text function:
function reverse_text(str)
local text = {}
for word in str:gmatch("[^%s]+") do
table.insert(text, 1, word)
end
return table.concat(text, " ")
end
and it turns:
#GThis #Yis #Ba #Mtest.
to
#Mtest. #Ba #Yis #GThis
The issue I'm running into with creating the string.match is the fact that colour codes can be in one of two formats:
#%a or #x%d%d%d
Additionally, I don't want it to return a colour code that doesn't colour, which is indicated as:
##%a or ##x%d%d%d
What's the best way to accomplish my end goal without compromising my requirements?
function wrap(str, limit, indent, indent1)
indent = indent or ""
indent1 = indent1 or indent
limit = limit or 79
local here = 1-#indent1
local last_color = ''
return indent1..str:gsub("(%s+)()(%S+)()",
function(sp, st, word, fi)
local delta = 0
local color_before_current_word = last_color
word:gsub('()#([#%a])',
function(pos, c)
if c == '#' then
delta = delta + 1
elseif c == 'x' then
delta = delta + 5
last_color = word:sub(pos, pos+4)
else
delta = delta + 2
last_color = word:sub(pos, pos+1)
end
end)
here = here + delta
if fi-here > limit then
here = st - #indent + delta
return "\n"..indent..color_before_current_word..word
end
end)
end

Resources